Skip to content

fix: re-plant the demo app's violations and guard them with a CI test - #48

Open
aanishs wants to merge 2 commits into
mainfrom
fix/replant-demo-app
Open

fix: re-plant the demo app's violations and guard them with a CI test#48
aanishs wants to merge 2 commits into
mainfrom
fix/replant-demo-app

Conversation

@aanishs

@aanishs aanishs commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Trust Sprint T3 (prep for #30 — the cold-run benchmark).

The problem: the demo app had been silently remediated in place — main.tf gained KMS encryption, blocked public ACLs, CloudTrail, and VPC flow logs; auth.ts gained bcrypt and a session timeout — while the README's violation table went stale. The benchmark target for em-dash's detection claims was mostly fixed, and nothing caught it.

This PR:

  • Restores the planted violations from the original planting commit (db27f21), keeping the later /comply-scan command fix
  • Moves the violation table out of the scanned tree — it is the answer key; the demo README now explains the public-set / held-out-set protocol instead
  • Adds test/demo-integrity.test.ts (12 assertions): any future 'fix' to a planted violation fails CI instead of passing silently. Enumerating the public set in-repo is by design — it's derivable from git history regardless; blind scoring uses a held-out set planted at run time and pre-registered via a timestamped public gist

All gates green locally: skill:check, biome, knip, and bun run test (the 4 dashboard-api failures are the known local-env flake, green in CI).

🤖 Generated with Claude Code

The demo app exists to BE broken, but phase-0 commits remediated it in place
(main.tf gained KMS/CloudTrail/flow logs, auth.ts gained bcrypt + session
timeout) while the README violation table went stale — silently corrupting
the benchmark target. This restores the planted violations from db27f21,
moves the violation table out of the scanned tree (it is the answer key),
and adds test/demo-integrity.test.ts so a future 'fix' to a planted
violation fails CI instead of passing silently.

Part of the Trust Sprint (issue #30 prep).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

em-dash Compliance Check


Compliance Summary — aanishs-em-dash
══════════════════════════════════════════════════
  Controls:    59 total, 0 complete (0%)
  Evidence:    0 items
  Signatures:  0

This is an informational check — it does not block merging.
Run /hipaa locally for a full interactive compliance audit.

@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR restores intentionally planted HIPAA violations in the demo app that had been silently remediated by earlier commits, and adds test/demo-integrity.test.ts — a 12-assertion CI suite that fails if any planted violation is ever "fixed" without a corresponding test update.

  • Violations across 7 files are re-planted (MD5 hashing, no session timeout, PHI in logs/localStorage/URLs/errors, open S3/RDS/IAM, no CloudTrail/VPC flow logs, realistic SSN fixtures, hardcoded secrets in .env.example).
  • The README violation table is removed from the scanned tree and replaced with documentation of the public-set / held-out-set benchmark protocol.
  • One integrity guard assertion (API_KEY=\S+) matches via substring on ANTHROPIC_API_KEY rather than checking the variable by its actual name; and the aws_lambda_function resource references an IAM policy ARN for its role attribute (which requires a role ARN) — an unintentional breakage not covered by any integrity test.

Confidence Score: 4/5

Safe to merge; the two findings are in non-production demo code and do not affect the tool's core behavior.

The core idea — re-planting violations and locking them with CI assertions — is sound and well-executed across 11 of the 12 tests. The API_KEY assertion passes via accidental substring matching, so the guard's intent is unclear to anyone maintaining it later. The aws_lambda_function role reference is a broken Terraform attribute that is undetected by any guard; while the TF is never applied, it introduces an unexplained deviation from the demo's educational goal of showing realistic-but-insecure infrastructure.

test/demo-integrity.test.ts (line 64 guard assertion) and demo/hipaa-demo-app/infra/main.tf (Lambda role attribute)

Important Files Changed

Filename Overview
test/demo-integrity.test.ts New CI integrity guard with 12 assertions; one assertion uses a substring match on the wrong env-var name (API_KEY vs ANTHROPIC_API_KEY), making the guard slightly misleading
demo/hipaa-demo-app/infra/main.tf Violations correctly restored; aws_lambda_function.role references an IAM policy ARN instead of an IAM role ARN — unintentional breakage not covered by any integrity test
demo/hipaa-demo-app/src/auth.ts MD5 hashing and no-session-timeout violations correctly restored; sessions Map is declared after the functions that reference it (works at runtime, slightly confusing ordering)
demo/hipaa-demo-app/src/api.ts No-RBAC, no-audit-logging, and PHI-in-errors violations correctly restored; 4 VIOLATION markers satisfy the integrity guard assertion of ≥3
demo/hipaa-demo-app/src/patients.ts PHI-in-console-log and PHI-in-error-message violations correctly restored; integrity test assertion pattern matches correctly
demo/hipaa-demo-app/src/patients.test.ts Realistic SSN fixtures restored as intended violation; SSNs used are well-known test values that do not correspond to real individuals
demo/hipaa-demo-app/src/dashboard.ts localStorage PHI, PHI-in-URL, and PHI-in-notifications violations correctly restored; integrity test anchors correctly on localStorage.setItem key name
demo/hipaa-demo-app/.env.example Hardcoded example credentials restored as violation; all values are well-known fictitious examples
demo/hipaa-demo-app/README.md Violation table removed from scanned tree; replaced with explanation of public-set / held-out-set scoring protocol

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Developer modifies\ndemo/hipaa-demo-app] --> B{Modifies a\nplanted violation?}
    B -- No --> C[PR merges normally]
    B -- Yes --> D[test/demo-integrity.test.ts\nreads file from disk]
    D --> E{Integrity assertion\npasses?}
    E -- Yes\nViolation still present --> C
    E -- No\nViolation was fixed --> F[CI fails ❌\nBlocks merge]
    F --> G[Developer must update\nintegrity test in same PR\nmaking change visible & reviewable]
    G --> C

    subgraph Benchmark Protocol
        H[Public planted set\nguarded by CI] --> I[em-dash demo scan]
        J[Held-out set\npre-registered gist] --> I
        I --> K[Blind detection score]
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Developer modifies\ndemo/hipaa-demo-app] --> B{Modifies a\nplanted violation?}
    B -- No --> C[PR merges normally]
    B -- Yes --> D[test/demo-integrity.test.ts\nreads file from disk]
    D --> E{Integrity assertion\npasses?}
    E -- Yes\nViolation still present --> C
    E -- No\nViolation was fixed --> F[CI fails ❌\nBlocks merge]
    F --> G[Developer must update\nintegrity test in same PR\nmaking change visible & reviewable]
    G --> C

    subgraph Benchmark Protocol
        H[Public planted set\nguarded by CI] --> I[em-dash demo scan]
        J[Held-out set\npre-registered gist] --> I
        I --> K[Blind detection score]
    end
Loading

Reviews (1): Last reviewed commit: "fix: re-plant the demo app's violations ..." | Re-trigger Greptile

Comment on lines +55 to 57
# VIOLATION: Security group with 0.0.0.0/0 — §164.312(a)(1)
resource "aws_security_group" "app" {
name = "hipaa-demo-app"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Lambda role references a policy ARN, not a role ARN

aws_iam_policy.app_policy.arn resolves to a policy ARN (arn:aws:iam::…:policy/…), but Lambda's role attribute requires an IAM role ARN (arn:aws:iam::…:role/…). The old aws_iam_role.lambda_role resource was removed in this PR without a replacement. While this TF is never applied, it would fail at terraform apply with an InvalidParameterValueException, and the breakage is not an enumerated violation — undermining the file's value as a realistic (if insecure) reference.

Comment on lines +61 to +65
test(".env.example contains hardcoded secrets (§164.312(a)(1))", () => {
const env = read(".env.example");
expect(env).toMatch(/AWS_SECRET_ACCESS_KEY=\S+/);
expect(env).toMatch(/API_KEY=\S+/);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 API_KEY guard matches wrong variable via substring

The assertion expect(env).toMatch(/API_KEY=\S+/) passes today because API_KEY= is a substring of ANTHROPIC_API_KEY=.... There is no standalone API_KEY variable in .env.example. If a future contributor reads this test and cross-references the file, they'll find no API_KEY= line — the guard silently shadows the actual variable name. The pattern should use ANTHROPIC_API_KEY=\S+ to unambiguously name the key being protected.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

…ble secret guards

The wildcard-policy violation stays planted (now attached to a proper role);
the Lambda role reference is a valid role ARN instead of a policy ARN. Secret
guards anchor on exact variable names so API_KEY can't match via substring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@aanishs

aanishs commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

Both Greptile P2s addressed in the follow-up commit: the Lambda now references a real aws_iam_role (with the wildcard policy attached to it, so the §164.308(a)(4) violation stays planted and the Terraform is actually valid), and the secret guards anchor on exact variable names (^AWS_SECRET_ACCESS_KEY=, ^ANTHROPIC_API_KEY=, ^STRIPE_SECRET_KEY= multiline) so API_KEY can't pass via substring match.

@github-actions

Copy link
Copy Markdown

em-dash Compliance Check


Compliance Summary — aanishs-em-dash
══════════════════════════════════════════════════
  Controls:    59 total, 0 complete (0%)
  Evidence:    0 items
  Signatures:  0

This is an informational check — it does not block merging.
Run /hipaa locally for a full interactive compliance audit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant