拓冰建站拓冰建站
首页 / 资讯中心 / 正文

面向物理隔离网络的代码上下文选择性导出工具设计与实现

SiloBrief 是一个面向物理隔离网络air-gapped networks的代码上下文选择性导出工具。在物理隔离网络中开发人员经常需要把部分代码上下文带出内网用于代码评审、问题分析、知识库整理或者为外部工具生成分析素材。但直接复制整个仓库既不安全也不高效。SiloBrief 的出发点很简单只导出与任务相关的代码上下文既不把整个代码库带出去也不丢失关键的函数、类、依赖和工程元信息。这篇文章会围绕 SiloBrief 的核心设计思路展开并带着你实现一个最小可用的同类型工具。你可以把它理解为一次“从零复刻核心机制”的演练也可以把它当作在自己的隔离网络环境中部署同类工具的参考。文章会依次说明物理隔离场景下的导出边界、上下文包应该长什么样、如何用 Python 快速实现文件筛选与符号提取、如何在打包后做验证以及实际生产环境里最容易踩的坑。适合阅读这篇文章的读者包括需要在隔离网络内整理代码交付物的一线开发人员负责网络安全与数据合规的工程师以及想理解“选择性导出代码上下文”这个设计理念的技术爱好者。读完以后你会得到一套可运行的示例代码并能够根据企业自身的安全策略继续扩展它。1. 先理解 SiloBrief 要解决的问题1.1 物理隔离网络中的代码导出为什么特殊物理隔离网络通常被部署在高安全要求的环境中例如研发内网、军工项目、金融核心系统、工业控制系统。它和外部网络之间不存在直接路由数据的进出往往依靠光闸、移动介质或人工审批。这种做法能有效阻断大部分远程攻击但也在日常开发中带来了新的问题内网里需要外部协作或外部工具分析代码时不能直接访问代码库。很多团队会退回到“人工复制代码片段”的方式。某个同事需要把一段代码交出去就直接选中文件内容粘贴到文档里需要交代项目结构时就手动把 tree 的输出整理一遍需要提供函数列表时又可能把生成文档的脚本跑到一半。这个过程容易遗漏也容易把不该带出的敏感数据一并带出。SiloBrief 要解决的正是这个痛点它让你在源仓库内执行一次受控的导出操作基于一套明确的规则生成一个“上下文包”。这个上下文包只包含被允许的代码文件和必要的元信息不包含凭证、密钥、日志、数据库文件等敏感内容。1.2 什么是代码上下文包含哪些维度代码上下文不是简单的“文件合集”。一份能被外部程序或评审人员真正读懂的上下文通常需要覆盖以下几个维度目录与文件结构让接收方知道代码的组织方式。关键文件内容根据导出目标选择出的源代码、配置、脚本和文档。符号与索引哪些函数、类、接口被定义了它们分布在哪些文件里。项目元信息代码版本、当前分支、是否包含未提交改动或者依赖清单。边界说明哪些目录被排除、哪些文件被选中让接收方理解上下文包为什么长这样。如果从内网导出的只是一个裸文件列表接收方往往还要先费力重建项目背景。SiloBrief 的思想是让导出结果自带“阅读指南”把文件名清单、符号索引和关键代码组织在同一个压缩包中并在导出时自动生成 manifest。1.3 选择性导出的边界在哪里“选择性”意味着两件事第一只能在隔离网络的允许范围之内工作第二默认策略应当是“尽量少导出”。在真正实施时需要先回答几个问题这一次导出是要解决什么问题是代码评审、缺陷排查还是给外部模型提供分析素材哪些文件是必需的哪些文件绝对不能被导出是否需要导出 git 提交信息和分支状态还是只导出源码快照导出包是否需要做加密和完整性校验这些问题的答案会写入规则文件。SiloBrief 的整个设计都围绕“显式声明”展开而不是依赖操作者临时手动选择。这样可以避免在紧张的工作环境下靠记忆和人工判断导致边界失控。注意物理隔离网络的数据合规责任不能全部交给一个 CLI 工具。规则文件只能减少人工失误真正的边界仍然应当由组织的安全策略、审批流程和人工审计共同保证。2. 参考设计SiloBrief 的上下文包格式2.1 上下文包内部应该有哪些文件一个经过良好设计的上下文包应当让人不需要重新访问内网就能理解代码背景。SiloBrief 的参考包结构可以设计成这样context-2025-01-07.zip ├── manifest.json ├── context.md └── files ├── src │ ├── main.py │ └── config.py ├── tests │ └── test_main.py └── README.md其中manifest.json是机器可读的索引context.md是给人阅读的上下文摘要files目录存放实际被选中的源文件。这样设计的好处是外部工具可以直接读取 JSON人工评审可以直接打开 Markdown真正需要看代码时再进入files目录。manifest.json并不需要非常大但建议包含这些关键字段字段含义示例name导出仓库或模块名称order-servicecreated_at导出时间UTC2025-01-07T08:30:00Zgit.head当前提交 SHA3f7a9c1git.branch当前分支maingit.dirty是否有未提交改动falsefiles_count被导出的文件数42total_size被导出文件总大小153600symbols_count提取到的符号数量128files文件级索引列表见下方示例files数组里的每一项可以记录路径、语言、大小和提取出的函数/类名。下面是一个最小示例[ { path: src/main.py, language: python, size: 4096, symbols: [run, OrderService, main] } ]2.2 考虑“什么人会读这份 manifest”设计上下文包格式时不要只想着机器。context.md的作用是让接收方在不解压的情况下先快速判断这个包是否与任务相关。context.md可以按下面这个结构生成# Project Context - Repository: order-service - Generated at: 2025-01-07T08:30:00Z - Git head: 3f7a9c1 (branch: main, dirty: false) ## File Index - src/main.py: run, OrderService, main - src/config.py: load_config, DEFAULT_PORT - tests/test_main.py: test_run_ok ## Selected Files - src/main.py - src/config.py - tests/test_main.py - README.md ## Excluded Patterns - .env - *.pem - .git/ - node_modules/有了这个文件接收方可以先阅读摘要再决定是否需要解压查看完整代码。它让“选择性导出”变得可审查也方便后续归档。2.3 规则作用顺序必须先定清楚SiloBrief 在筛选文件时规则之间的优先级一旦不清楚就会导致意外导出。建议使用如下顺序默认排除目录例如.git/、node_modules/、__pycache__/、build/、dist/。读取.gitignore遵循仓库自身的忽略规则。应用敏感文件排除规则例如.env、*.pem、*.key、*.log、*.db。应用显式allow白名单只有命中这里规则的文件才进入候选集合。应用显式deny黑名单在最后一步强制排除。在这个顺序下即使你在allow里写了**/*只要.env命中敏感规则仍然不会被导出。这个“最后黑名单兜底”的设计非常重要因为人工操作时最容易犯错的地方就是白名单范围过大。3. 从零实现一个最小可用的 SiloBrief 核心这一部分会实现一个名为silobrief的最小命令行工具。代码使用 Python 3依赖只有PyYAML用于读取 YAML 规则文件。目标是跑通“扫描源码 - 按规则筛选 - 提取符号 - 生成 manifest - 打包 zip”的完整链路。3.1 环境准备在开始前需要准备好下面的环境环境项要求操作系统Linux、macOS 或 Windows 均可Python3.9 及以上PyYAML5.4 及以上示例项目任意一个本地源码目录安装 PyYAML 只需要一条命令pip install pyyaml如果你所在的隔离网络内没有公共 PyPI 源可以考虑从有外网的环境下载PyYAML的 wheel 包再通过移动介质导入。这里的代码也会尽量把第三方依赖控制在最小范围内减少内网部署的阻力。3.2 项目结构和配置项目目录可以设计成这样silobrief-demo/ ├── silobrief.py ├── requirements.txt ├── example/ │ ├── .silobrief.yml │ └── src/ │ ├── main.py │ └── config.pyrequirements.txt内容PyYAML5.4在example/目录下准备一个.silobrief.yml规则文件version: 1 default_exclude: - .git - node_modules - __pycache__ - build - dist sensitive: - .env - .env.* - *.key - *.pem - *.p12 - *.pfx - *.log - *.db - *.sqlite - token* - secret* allow: - src/** - tests/** - docs/** - README* - *.toml - *.yaml - *.yml deny: - src/generated/** max_file_size: 1048576 extensions: - .py - .js - .ts - .java - .go - .c - .h - .cpp - .md - .json - .yaml - .yml - .toml这里default_exclude是内置的目录忽略sensitive是敏感文件allow是白名单deny是最后黑名单。后面的代码会严格按照这个顺序处理。3.3 编写 CLI 入口打开silobrief.py首先完成参数解析和配置加载#!/usr/bin/env python3 SiloBrief 最小实现示例。 在物理隔离网络场景中选择性导出代码上下文。 import argparse import fnmatch import json import os import re import sys import time import zipfile from datetime import datetime, timezone from pathlib import Path from typing import Dict, List, Optional try: import yaml except ImportError: print(缺少 PyYAML请先执行: pip install pyyaml) sys.exit(1) def load_config(path: Path) - Dict: if not path.exists(): return {} with open(path, r, encodingutf-8) as f: data yaml.safe_load(f) return data or {} def parse_args(): parser argparse.ArgumentParser( descriptionSelectively export code context from air-gapped networks ) parser.add_argument( --repo, typePath, defaultPath(.), help源代码仓库根路径默认是当前目录, ) parser.add_argument( --output, typePath, defaultNone, help输出 zip 包路径默认是 silobrief-时间戳.zip, ) parser.add_argument( --config, typePath, defaultNone, help规则文件路径默认是 repo/.silobrief.yml, ) parser.add_argument( --no-git, actionstore_true, help不读取 git 元数据, ) return parser.parse_args() def guess_language(path: Path) - str: suffix path.suffix.lower() mapping { .py: python, .js: javascript, .ts: typescript, .java: java, .go: go, .c: c, .cpp: cpp, .h: c-header, .md: markdown, .json: json, .yaml: yaml, .yml: yaml, .toml: toml, } return mapping.get(suffix, text)这段代码建立了最基本的参数体系和使用体验。之后运行命令时可以只指定--repo其余参数使用默认值。3.4 实现文件筛选规则筛选是整个工具的核心。下面这个函数把“候选文件”和“规则文件”放在一起判断def matches_any(path: str, patterns: List[str]) - bool: for pattern in patterns: if fnmatch.fnmatch(path, pattern): return True return False def collect_candidates(repo: Path, config: Dict) - List[Path]: default_exclude config.get(default_exclude, []) sensitive config.get(sensitive, []) allow config.get(allow, []) deny config.get(deny, []) max_size int(config.get(max_file_size, 5_000_000)) # 如果题目中没有提供 allow就默认放行所有文件。 allow_all not allow candidates [] for root, dirs, files in os.walk(repo): root_path Path(root) rel_root root_path.relative_to(repo).as_posix() # 过滤目录 keep_dirs [] for d in sorted(dirs): rel rel_root / d if rel_root ! . else d if d.startswith(.git) or matches_any(rel, default_exclude): continue keep_dirs.append(d) dirs[:] keep_dirs for f in sorted(files): full_path root_path / f rel_full full_path.relative_to(repo).as_posix() # 默认排除和敏感规则 if matches_any(rel_full, default_exclude): continue if matches_any(rel_full, sensitive): continue # 白名单 if not allow_all and not matches_any(rel_full, allow): continue # 黑名单最后生效 if matches_any(rel_full, deny): continue # 后缀和大小检查 suffix full_path.suffix.lower() allowed_ext config.get(extensions, []) if allowed_ext and suffix not in allowed_ext: continue try: if full_path.stat().st_size max_size: continue except OSError: continue candidates.append(full_path) return candidatesfnmatch.fnmatch的实现会匹配跨目录的文件名因此src/**这样的写法可以匹配src/main.py和src/lib/util.py。虽然是近似实现但已经足够覆盖常规场景。3.5 提取函数和类符号提取符号不需要接入完整语法树可以用一个保守的正则集合完成。这里给出一个最小实现SYMBOL_PATTERNS [ re.compile(r^class\s(\w)), re.compile(r^def\s(\w)), re.compile(r^func\s(\w)), re.compile(r^function\s(\w)), re.compile(r^\s*(?:public\s|private\s|protected\s)?(?:class|interface|enum)\s(\w)), ] def extract_symbols(path: Path) - List[str]: symbols [] try: with open(path, r, encodingutf-8, errorsignore) as f: for line in f: stripped line.strip() for pattern in SYMBOL_PATTERNS: m pattern.match(stripped) if m: symbols.append(m.group(1)) break except OSError: pass return symbols这份实现并不精确。针对一个大型 Java 或 TypeScript 文件可能会漏掉嵌套函数或方法。实际项目中可以使用树状语法分析器但为了保持最小演示正则已经足够展示“代码上下文索引”的概念。3.6 生成 manifest 和 Markdown 摘要接下来把候选文件的信息汇总成manifest.json和context.mddef build_manifest( repo: Path, files: List[Path], config: Dict, no_git: bool False, ) - Dict: file_records [] total_size 0 symbols_count 0 for path in files: rel path.relative_to(repo).as_posix() size 0 try: size path.stat().st_size except OSError: pass symbols extract_symbols(path) symbols_count len(symbols) total_size size file_records.append( { path: rel, language: guess_language(path), size: size, symbols: symbols, } ) manifest { name: repo.name or project, created_at: datetime.now(timezone.utc).strftime(%Y-%m-%dT%H:%M:%SZ), files_count: len(file_records), total_size: total_size, symbols_count: symbols_count, files: file_records, rules: { allow: config.get(allow, []), deny: config.get(deny, []), sensitive: config.get(sensitive, []), }, } if not no_git: manifest[git] read_git_info(repo) return manifest def read_git_info(repo: Path) - Optional[Dict]: try: import subprocess head ( subprocess.check_output( [git, -C, str(repo), rev-parse, --short, HEAD], stderrsubprocess.DEVNULL, ) .decode() .strip() ) branch ( subprocess.check_output( [git, -C, str(repo), rev-parse, --abbrev-ref, HEAD], stderrsubprocess.DEVNULL, ) .decode() .strip() ) dirty subprocess.call( [git, -C, str(repo), diff, --quiet], stderrsubprocess.DEVNULL, ) ! 0 return {head: head, branch: branch, dirty: dirty} except Exception: return None def build_context_md(manifest: Dict) - str: lines [ # Project Context, , f- Repository: {manifest.get(name)}, f- Generated at: {manifest.get(created_at)}, ] git manifest.get(git) if git: lines.append(f- Git head: {git.get(head)} (branch: {git.get(branch)}, dirty: {git.get(dirty)})) lines [, ## File Index] for rec in manifest.get(files, []): syms , .join(rec.get(symbols, [])) line f- {rec[path]}: {syms} lines.append(line) lines [, ## Selected Files] for rec in manifest.get(files, []): lines.append(f- {rec[path]}) runs manifest.get(rules, {}) deny runs.get(deny) if deny: lines [, ## Excluded Patterns, ] lines [f- {p} for p in deny] return \n.join(lines) \n这里的context.md可以作为人工检查的第一页。接收方不需要逐个解压文件就能知道导出了什么、排除了什么。3.7 打包输出最后一步是把文件和索引写入 zipdef create_package( repo: Path, output: Path, manifest: Dict, context_md: str, files: List[Path], ) - None: with zipfile.ZipFile(output, w, zipfile.ZIP_DEFLATED) as zf: zf.writestr(manifest.json, json.dumps(manifest, ensure_asciiFalse, indent2)) zf.writestr(context.md, context_md) for path in files: rel path.relative_to(repo).as_posix() zf.write(path, arcnameffiles/{rel}) def main(): args parse_args() repo: Path args.repo.resolve() if not repo.is_dir(): print(f错误仓库路径不存在 {repo}) sys.exit(1) config_path args.config if config_path is None: config_path repo / .silobrief.yml config_path Path(config_path) config load_config(config_path) if not args.output: output repo.parent / fsilobrief-{int(time.time())}.zip else: output Path(args.output) files collect_candidates(repo, config) if not files: print(警告没有选出任何文件请检查规则配置。) sys.exit(2) manifest build_manifest(repo, files, config, no_gitargs.no_git) context_md build_context_md(manifest) create_package(repo, output, manifest, context_md, files) print(f导出完成{output}) print(f文件数{manifest[files_count]}符号数{manifest[symbols_count]}) print(f大小{manifest[total_size]} 字节) if __name__ __main__: main()到这里一个最小可用的 SiloBrief 就完成了。它还非常粗糙但已经具备“选择性导出代码上下文”的完整流程。4. 运行验证与结果分析4.1 准备一个示例项目在example/目录下创建两个源码文件。src/main.py示例内容class OrderService: def create_order(self, user_id, items): return order-123 def main(): service OrderService() print(service.create_order(u1, [])) if __name__ __main__: main()src/config.py示例内容DEFAULT_PORT 8080 def load_config(path): return {port: DEFAULT_PORT}同时准备一个README.md内容随意。再故意放一个.env文件测试敏感规则是否生效DB_PASSWORDshould-not-export API_KEYshould-not-export4.2 执行导出命令在silobrief-demo/目录下执行python silobrief.py --repo example --output example-out.zip如果希望在非 git 目录中运行可以加上--no-gitpython silobrief.py --repo example --output example-out.zip --no-git正常情况下输出类似导出完成example-out.zip 文件数4符号数4 大小1024 字节这里的文件数包括README.md、src/main.py、src/config.py以及可能被白名单匹配到的.silobrief.yml配置文件本身。因为配置文件在example/根目录且后缀.yml在 extensions 允许范围内它也会被选中。4.3 检查 zip 包内容解压example-out.zip查看内部结构unzip -l example-out.zip然后读取manifest.jsonunzip -p example-out.zip manifest.json | python -m json.tool重点看两个地方git字段是否存在files数组里是否有.env。正常情况下.env不会出现在文件列表中因为它命中了sensitive规则。4.4 验证敏感文件没有被导出这是整个工具最关键的一次验证。在命令行里直接列出 zip 中的文件然后搜索敏感后缀unzip -Z1 example-out.zip | grep -E (\.env|\.pem|\.key|\.log|\.db)正确结果是什么也没有退出码为 1表示匹配不到。如果这个命令输出了文件说明规则配置或筛选逻辑出现了问题需要立刻停止导出并检查规则。注意不要只验证“程序能启动”。在物理隔离场景中验证“不该导出的文件没有出现”比“导出成功”重要得多。5. 常见问题排查5.1 为什么明明 exclude 了.env导出包里还有这通常是因为allow规则和default_exclude或sensitive规则的判断顺序出现了偏差。在本文实现里sensitive的优先级高于allow因此只要命中.env就不会进入候选列表。如果你在其他实现中看到.env被导出可以按下面顺序检查检查规则文件是否被正确加载比如路径是否指向了错误的/path/.silobrief.yml。检查sensitive规则里是否写成了*.env而实际文件叫.env导致 glob 不匹配。检查是否在筛选逻辑的最后一步又执行了一次“恢复所有 allow 文件”的逻辑。.env这类文件名以点开头使用通配时很容易出错。建议在规则文件中针对它写两条规则.env和.env.*。5.2 为什么选中文件数不是预期的值常见原因有三个现象可能原因检查方式导出文件偏少allow白名单没有覆盖到目标目录打印collect_candidates中间结果检查匹配 pattern导出文件偏多没有配置extensions过滤检查默认extensions是否为空或者配置被覆盖大文件意外导出max_file_size设置过大或未生效在配置里把大小调整为较小值比如102400排查时可以在collect_candidates函数内部加一条调试输出打印每个候选文件命中的规则。这样能很快定位是路径匹配问题还是逻辑顺序问题。5.3 符号提取不到或者提取到不相关内容怎么办正则方式的符号提取精度有限。如果遇到以下情况大量方法定义没有被识别因为缩进导致正则要求行首顶格类名被错误识别为函数名注解或装饰器影响了匹配结果。可以考虑引入真实的代码解析库例如 Python 的tree-sitter、Java 的javaparser、Go 的go/ast。物理隔离网络的部署环境下你要先把对应依赖的离线包带入内网再配置到导出工具的运行环境中。5.4 zip 包在接收方环境打不开先检查本地的 zip 文件是否完整。可以执行python -c import zipfile; zipfile.ZipFile(example-out.zip).testzip()如果 zip 文件没有问题再看接收方使用的解压工具是否支持ZIP_DEFLATED压缩算法。绝大多数操作系统自带解压工具都支持但对老旧工具的兼容性仍然要提前确认。6. 生产环境使用 SiloBrief 的最佳实践6.1 规则文件要纳入版本管理不要把.silobrief.yml当作临时文件。规则文件一旦被修改导出的上下文边界就改变了。建议把它纳入代码库版本管理并由负责安全合规的同事 review 每次变更。这样每个上下文包的规则都是可追溯的。例如在真实项目里你可以让规则文件长这样# 本次导出的任务编号INC-2025-0112 # owner: security-team version: 1 allow: - order/src/main/** - order/src/main/resources/** - order/pom.xml deny: - order/src/main/resources/application-prod.yml在代码注释中记录任务编号和负责人能让后续审计更清晰。6.2 导出前必须经过自动和人工双重检查自动检查可以包括扫描 zip 包中的文件后缀和文件名。匹配常见敏感文件关键词例如password、secret、token、api_key。校验 manifest 中的文件数、大小和符号数是否在合理范围。人工检查则需要打开context.md确认以下几点导出文件是否与任务相关。是否包含未在deny列表中出现的敏感路径。是否包含 bin、log、db、证书等不应出现的文件类型。下面的检查清单可以在每次导出前使用检查项确认方式结果规则文件已提交git diff --name-only无未预期改动.env等敏感文件未包含unzip -Z1grep expired输出目录未混入历史包清理旧输出目录已完成manifest 文件数合理阅读--files_count与预期一致git 状态明确查看git.dirty字段已确认6.3 给导出包增加完整性校验物理隔离网络中的数据转移往往要通过移动介质或人工审批。无论采用哪种方式导出包都可能被复制、替换或损坏。建议在导出后生成 SHA-256 摘要并将摘要与上下文包分开传递sha256sum example-out.zip example-out.zip.sha256接收方拿到包后重新计算哈希确认和摘要一致后再解压。这个步骤能防止传输过程中的意外损坏也能提供最基本的完整性保障。6.4 考虑加密和访问控制如果上下文包中的源码依然敏感可以在导出流程中增加加密步骤。最小方案是使用 GPG 对称加密gpg --symmetric --cipher-algo AES256 example-out.zip这样即使上下文包在传输过程中被截获没有密码也无法直接读取源码。但这个方案要求接收方通过安全渠道拿到密码并且不要和压缩包一起传递。6.5 区分学习环境和生产环境学习环境里你可以直接运行python silobrief.py在本地生成一个 zip 包反复调整规则。生产环境则至少需要做以下改造将规则文件外置避免每次打包都要修改仓库。增加日志输出记录每次导出的时间、操作者、文件数和规则版本。接入权限控制限制谁能执行真正的导出命令。增加审计把每次导出生成的manifest.json留档。建立回滚机制一旦发现误导出敏感文件能够通过 manifest 快速定位影响范围。这些改造需要结合公司现有的安全流程。SiloBrief 只是导出工具真正决定是否允许导出的是流程和权限体系。7. 可以继续扩展的方向7.1 接入真实语法分析器正则的符号提取适合做成快速索引但不够精确。下一步可以把extract_symbols替换成tree-sitter或各语言自带的 AST 工具。这样能准确提取方法参数列表、接口定义、引用关系甚至可以生成“这个改动会影响哪些函数”的调用链摘要。在内网环境下通常需要先把语言解析器编译成静态二进制文件准备好离线依赖再部署到隔离网络内的执行节点上。7.2 支持增量导出如果同一个仓库需要反复导出上下文每次全量扫描会产生大量重复内容。增量导出可以基于 git 历史只导出两个提交之间发生变化的文件同时保留必要的工程元信息。这能显著减少上下文包大小也降低敏感数据暴露面。增量模式下manifest 需要记录base_commit和head_commit接收方才能理解增量内容。7.3 集成邮件审批与审计系统生产级 SiloBrief 可以把“生成上下文包”和“允许导出”解耦。生成包之后先自动扫描敏感内容再发给安全组审批。审批通过后才允许把包复制到移动介质或上传到指定出口位置。这条链路可以对接企业现有的工单、审批、日志系统。具体实现时可以给 SiloBrief 增加一个--dry-run模式只输出将要导出的文件清单不生成 zip 包。7.4 针对不同接收方定制输出模板不同接收方关心的上下文不一样。安全评审需要依赖清单和文件变化范围AI 工具有时需要完整的函数体而不是函数名知识库整理则需要 Markdown 摘要。把“文件筛选”与“内容渲染”分开可以让 SiloBrief 在一套规则基础上输出多种格式。例如输出格式用途核心内容zip完整代码上下文包源码、manifest、context.mdmarkdown人工阅读文件索引、符号摘要、规则记录json机器处理结构化文件列表、符号和 git 状态这样既能满足不同安全级别下的导出需求也能保证底层的筛选逻辑保持一致。编写这类工具时最重要的不是代码技巧而是“始终知道自己导出了什么、没有导出什么”。SiloBrief 的思想看起来简单但在物理隔离网络中它把一次原本容易失控的人工操作变成了一个可配置、可审计、可验证的技术流程。希望这篇文章的资源可以帮助你理解并实现自己的选择性代码上下文导出工具。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门