
Evidence-driven C/C++ vulnerability remediation pipeline + http-parser case study (CVE-2024-22019-class). Python core, React 19 console, 17-test verification suite.
An MVP that normalizes vulnerability findings in C/C++ protocol/platform code into reproducible evidence and validates candidate patches in isolated copies. code-shield was a working name with a confirmed name-collision risk, so a neutral internal name is used for the public package and CLI.
The focus of the current implementation is not a patch-generation model but the verification closed loop below.
sanitizer 또는 SARIF
-> Finding + EvidenceBundle
-> source context
-> manual/external-agent patch
-> 원본 재현
-> build
-> patched reproducer
-> tests
-> static rescan
-> bounded refuzz
-> protocol oracle
-> verified report
Finding, EvidenceBundle, PatchProposal,
VerificationReport JSON modelsdetected → reproducible → contextualized → proposed → plausible → verified state transitionsThere are no runtime Python dependencies.
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/python -m unittest discover -s tests -v
To run without installing:
PYTHONPATH=src python3 -m protocol_remediator --help
PYTHONPATH=src python3 -m unittest discover -s tests -v
The dynamic end-to-end suite is a C/C++ fixture matrix under examples. It actually reproduces CWE-121, CWE-190, CWE-416, CWE-787, and CWE-476 with Clang ASan/UBSan, then runs all six gates against a patch that restores each invariant. Per-fixture inputs and verification scope are documented in examples/README.md.
To run only the real matrix without a unit-test framework:
PYTHONPATH=src python3 examples/run_fixture_matrix.py
To auto-generate and run more C/C++ variant examples:
PYTHONPATH=src python3 examples/run_generated_corpus.py --count 50
This runner does not use unittest; it passes each generated project through the same VerificationPipeline. The result summary is written to artifacts/generated-corpus-summary.json by default.
A Vite + React + TypeScript frontend that lets you inspect the current implementation state as an operational dashboard lives in frontend. This console brings the fixture matrix, generated corpus, Hermes API server connectivity, verification gates, and evidence safety invariants together on one screen.
cd frontend
npm install
npm run dev
The default dev server is http://127.0.0.1:5173. Verify a production build with:
cd frontend
npm run build
protocol-remediator ingest-sanitizer \
--log asan.log \
--reproducer crash.input \
--target-name parser \
--revision 0123456789abcdef \
--variant asan-x86_64 \
--output intake/parser-crash
Output:
intake/parser-crash/finding.json
intake/parser-crash/evidence.json
protocol-remediator ingest-sarif \
--sarif results.sarif \
--output intake/sarif
protocol-remediator export-sarif \
--finding intake/parser-crash/finding.json \
--finding intake/another/finding.json \
--output artifacts/findings.sarif
protocol-remediator context \
--finding intake/parser-crash/finding.json \
--evidence intake/parser-crash/evidence.json \
--target-root /path/to/target \
--output intake/parser-crash/context.json
protocol-remediator verify \
--config /path/to/target/target.toml \
--finding intake/parser-crash/finding.json \
--evidence intake/parser-crash/evidence.json \
--patch candidate.patch \
--artifacts artifacts
Exit code is 0 on verified, 1 on verification failure, and 2 on configuration or input errors.
Starting the Hermes API server lets remediate request patches via HTTP API instead of a local command. The default endpoint is POST /v1/patches; it accepts finding/evidence/context and a target workspace archive and returns a unified diff.
Example server run:
PYTHONPATH=src python3 -m protocol_remediator.hermes_server \
--host 127.0.0.1 \
--port 8765
After installation, the console script is also available.
hermes-agent-server --host 127.0.0.1 --port 8765
To attach an operational backend command, repeat --backend-command for each argument. The {context}, {workspace}, and {patch_output} placeholders are supported.
hermes-agent-server \
--backend-command my-patch-agent \
--backend-command --context \
--backend-command {context} \
--backend-command --workspace \
--backend-command {workspace} \
--backend-command --output \
--backend-command {patch_output}
In target.toml, specify Hermes mode like this:
[agent]
mode = "hermes"
url = "http://127.0.0.1:8765"
timeout_seconds = 30
Then use the existing remediate command as-is.
protocol-remediator remediate \
--config examples/length-prefixed-parser/target.hermes.toml \
--finding artifacts/hermes-cli-input/finding.json \
--evidence artifacts/hermes-cli-input/evidence.json \
--artifacts artifacts/hermes-cli
For a development end-to-end check, run the following runner. It starts a temporary Hermes server, obtains a patch via the API client, and runs the verification closed loop to completion.
PYTHONPATH=src python3 examples/run_hermes_demo.py
To call a local command directly without Hermes, specify the agent command as a string array in target.toml.
[agent]
mode = "command"
command = [
"my-patch-agent",
"--context",
"{context}",
"--workspace",
"{workspace}",
"--output",
"{patch_output}",
]
timeout_seconds = 900
Then run:
protocol-remediator remediate \
--config /path/to/target/target.toml \
--finding intake/parser-crash/finding.json \
--evidence intake/parser-crash/evidence.json \
--artifacts artifacts
The core does not directly call any particular LLM API. The contract is that a Hermes backend or an external command reads the context and generates a unified diff. Agent work runs on a temporary copy, not the original target.
A complete example is in target.toml.
[project]
name = "my-protocol"
language = "c++"
root = "."
[executor]
mode = "docker"
image = "my-frozen-toolchain@sha256:..."
timeout_seconds = 300
network = false
[reproduction]
failure_regex = "AddressSanitizer|heap-buffer-overflow"
[verification]
required_gates = [
"build",
"reproducer",
"tests",
"rescan",
"refuzz",
"protocol",
]
[gates]
build = [["cmake", "-S", ".", "-B", "build"], ["cmake", "--build", "build"]]
reproducer = [["./build/fuzz_target", "{reproducer}"]]
tests = [["ctest", "--test-dir", "build", "--output-on-failure"]]
rescan = [["./tools/run-sast", "--fail-on-new"]]
refuzz = [["./tools/refuzz", "--seconds", "60"]]
protocol = [["./tools/protocol-oracle"]]
Each command is an argument array rather than a shell string. Supported placeholders:
{workspace}: the temporary target path as visible to the executor{reproducer}: the reproducer path copied into the temporary target after checksum verificationbuild and reproducer are always required. Under the default policy, all six gates are mandatory. If a gate cannot be used due to the target's characteristics, it must be explicitly adjusted in required_gates, and that remains visible in the report.
Each verification run preserves the following:
artifacts/run_<id>/
candidate.patch
context.json
evidence.input.json
finding.input.json
finding.final.json
patch-proposal.json
patch-stats.json
verification-report.json
verification-report.json contains the outputs of both the baseline and patched commands. Since PoCs or logs may contain secrets, a separate access and retention policy should be applied to the artifact store.
network=false.allow_local=true and must not be used on untrusted targets.plausible is a state in which only the build and the original reproducer have passed.verified is not a proof of program equivalence either, and it does not replace human approval.The research rationale and design decisions are documented in docs/research.