Files
accounted/.claude/skills/iso-27001-2022-compliance/references/violation-patterns.md
T
Jakob Wennberg ec27228a8e style: remove em/en dashes repo-wide, add CLAUDE.md rule against them (#890)
Em dashes (—) and en dashes (–) had spread across comments, docs, tests,
and a few UI strings, reading as AI-generated boilerplate rather than
house style. Replaced each with punctuation matching its context: colon
for explanatory clauses, comma for asides, plain hyphen for numeric/legal
ranges (e.g. "21-23§"), "to"/"till" for date ranges, parentheses for
paired-dash asides. messages/en.json and messages/sv.json were fixed by
hand together to keep sv/en in sync.

Left untouched where the dash is the functional subject rather than
decorative punctuation: date-range-parser.ts's separator regex,
charset-repair.ts's CP1252 byte-mapping table (and its test), the SIE
encoding mojibake docs, generic-csv.ts's minus-sign normalizer, the
agent system-prompt files that already instruct against em dashes, and
a golden iXBRL test fixture compared byte-for-byte.

Also fixes two bugs surfaced along the way: an off-by-one in
ApiKeysPanel's scope-label split (a leftover from an earlier partial
pass), and a charset-repair test that had lost the literal en-dash it
exists to verify.

Regenerated the agent atom seed migration (skills:generate) since 27
SKILL.md files changed. Added a CLAUDE.md rule against em/en dashes,
with an explicit carve-out for the functional-dash cases above.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 15:58:06 +02:00

9.1 KiB

Violation Patterns: Code, Configuration, Dependency

This file catalogs concrete violation patterns the scanner must detect. Patterns are organized by where they live in the repository: source code, infrastructure-as-code, or dependency manifests.

For each pattern: the violation, the controls violated, and the detection logic.


Code-level violations

SQL injection via string concatenation

Controls violated: A.8.28 (Secure coding), A.8.3 (Information access restriction). Pattern:

query = "SELECT * FROM users WHERE id = " + user_input
cursor.execute(query)

Detection: SAST rule (Semgrep, CodeQL) flagging string concatenation into SQL execution functions. Compare to parameterized form cursor.execute("SELECT * FROM users WHERE id = %s", (user_input,)).

Command injection via shell concatenation

Controls violated: A.8.28. Pattern:

os.system("ping " + user_input)
subprocess.call(f"git clone {repo_url}", shell=True)

Detection: SAST rule for os.system, subprocess.* with shell=True and unsanitized inputs.

Hardcoded secrets

Controls violated: A.8.24 (Use of cryptography), A.5.17 (Authentication information). Pattern:

AWS_SECRET_KEY = "AKIAIOSFODNN7EXAMPLE"
db_password = "p@ssw0rd123"

Detection: Entropy analysis + regex (Trivy secret scanner, gitleaks, truffleHog). Scan full Git history, not just current HEAD: secrets in old commits are still exposed.

Weak cryptography

Controls violated: A.8.24. Patterns:

import hashlib
hashlib.md5(password.encode())  # Broken
hashlib.sha1(password.encode())  # Broken
crypto.createHash('md5')  // Broken

Detection: SAST rule for MD5, SHA-1, DES, RC4, ECB mode, or hashing without salt for password storage. Required alternatives: SHA-256+ for hashing, bcrypt/argon2/scrypt for passwords.

Missing input validation on PII handlers

Controls violated: A.8.11 (Data masking), A.5.34 (Privacy and protection of PII). Pattern: Functions that accept PII parameters and write them to logs, return them in error messages, or store them unencrypted. Detection: Tag-based SAST: annotate PII-handling functions and verify masking/redaction is applied before output sinks (logs, errors, storage).

Insecure deserialization

Controls violated: A.8.28. Patterns:

pickle.loads(user_input)
yaml.load(user_input)  # Without SafeLoader

Detection: SAST rule for known-unsafe deserializers with untrusted input.

Path traversal

Controls violated: A.8.3, A.8.28. Pattern:

open(os.path.join(base_dir, user_provided_filename))

Detection: SAST rule for filesystem operations using unsanitized user input. Required guard: realpath check that resolved path is within base_dir.


Configuration-level violations (IaC)

Public storage buckets

Controls violated: A.8.12 (DLP), A.8.3 (Access restriction), A.5.34. Patterns:

resource "aws_s3_bucket" "data" {
  acl = "public-read"
}
resource "aws_s3_bucket_public_access_block" "data" {
  block_public_acls = false
  block_public_policy = false
}

Detection: Checkov CKV_AWS_53, CKV_AWS_54, CKV_AWS_55, CKV_AWS_56.

Wildcard IAM permissions

Controls violated: A.8.2 (Privileged access rights). Pattern:

{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}

Detection: Checkov CKV_AWS_1, CKV_AWS_46, CKV_AWS_49. JSON path query for any policy statement with Action: * AND Resource: *. Some narrow exceptions exist (e.g., iam:GetUser on self) but *:* is never justifiable.

Unencrypted storage

Controls violated: A.8.24. Patterns:

resource "aws_ebs_volume" "data" {
  encrypted = false  # Or omitted (default false in older provider versions)
}

resource "aws_db_instance" "main" {
  storage_encrypted = false
}

Detection: Checkov CKV_AWS_3 (EBS), CKV_AWS_16 (RDS), CKV_AWS_17 (RDS publicly accessible), CKV_AWS_19 (S3 server-side encryption).

Database in public subnet

Controls violated: A.8.20 (Network security), A.8.22 (Segregation of networks). Pattern: RDS / managed database resource attached to a subnet whose route table has a route to an Internet Gateway, plus a security group allowing 0.0.0.0/0 ingress on the database port. Detection: Graph-based check (Checkov supports this via cross-resource attribute queries).

Unrestricted security group ingress

Controls violated: A.8.20, A.8.22. Pattern:

resource "aws_security_group" "open" {
  ingress {
    from_port = 0
    to_port = 65535
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Detection: Checkov CKV_AWS_24 (port 22 / SSH from 0.0.0.0/0), CKV_AWS_25 (port 3389 / RDP), generic checks for all-port ingress from 0.0.0.0/0.

Missing TLS enforcement

Controls violated: A.8.20, A.8.24. Patterns:

resource "aws_lb_listener" "http" {
  protocol = "HTTP"  # Should be HTTPS
  port = 80
}

S3 buckets without bucket policy denying non-HTTPS requests. Detection: Checkov CKV_AWS_2 (ALB listener HTTPS), CKV_AWS_103 (TLS 1.2+ for ALB), CKV_AWS_91 (ALB access logging).

Privileged containers

Controls violated: A.8.18 (Use of privileged utility programs). Pattern:

spec:
  containers:
    - name: app
      securityContext:
        privileged: true
        runAsUser: 0
        capabilities:
          add: ["SYS_ADMIN"]

Detection: Checkov CKV_K8S_16, CKV_K8S_20, CKV_K8S_22.

Missing resource limits

Controls violated: A.8.6 (Capacity management). Pattern: Kubernetes containers without resources.limits.cpu and resources.limits.memory. Detection: Checkov CKV_K8S_10, CKV_K8S_11, CKV_K8S_12, CKV_K8S_13.

Missing logging

Controls violated: A.8.15 (Logging). Pattern: AWS resources without CloudTrail enabled, S3 buckets without access logging, VPCs without flow logs. Detection: Checkov CKV_AWS_67 (CloudTrail multi-region), CKV_AWS_18 (S3 access logging), CKV_AWS_11 (VPC flow logs).

Unprotected branch

Controls violated: A.8.4 (Access to source code), A.8.32 (Change management). Pattern: GitHub main / master branch without protection rules requiring PR review, status checks, and signed commits. Detection: Steampipe query against GitHub API, or scan of .github/settings.yml if probot/settings is used.


Dependency-level violations

Known CVEs in production dependencies

Controls violated: A.8.8 (Management of technical vulnerabilities), A.8.30 (Outsourced development). Detection: Trivy / Snyk / Dependabot scanning package-lock.json, requirements.txt, go.sum, Cargo.lock, pom.xml, Gemfile.lock, composer.lock. Threshold: any CVSS ≥ 7.0 with available patch is blocking.

Unpinned dependencies

Controls violated: A.8.8, A.8.32. Patterns:

# requirements.txt
requests
django>=3.0
// package.json
"lodash": "^4.0.0"

Detection: Manifest parsing for version specifiers using >=, ^, ~, or no version. Floating versions break reproducibility and audit trail.

Missing lockfile

Controls violated: A.8.32 (Change management). Pattern: package.json without package-lock.json, requirements.txt without requirements.lock or Pipfile.lock. Detection: Filesystem check.

Abandoned / unmaintained dependencies

Controls violated: A.8.8, A.8.30. Detection: Cross-reference dependency list with deps.dev / libraries.io / OSV to detect packages with no commits in >24 months.

License risk

Controls violated: A.5.32 (Intellectual property rights). Detection: License scanner (FOSSA, Black Duck, license-checker) flagging GPL-3.0, AGPL-3.0, SSPL where they conflict with the repository's own licensing strategy.

Typosquatting / dependency confusion

Controls violated: A.8.30, A.5.21 (ICT supply chain). Detection: Known-bad-package lists, registry mirror verification, internal package namespace enforcement.


Pipeline-level violations

SAST not in pipeline

Controls violated: A.8.28, A.8.29. Detection: Parse .github/workflows/*.yml and .gitlab-ci.yml. Verify a SAST step (Semgrep, CodeQL, SonarQube, Snyk Code) runs on every PR targeting protected branches.

SCA not in pipeline

Controls violated: A.8.8. Detection: As above, for SCA steps (Trivy, Snyk, Dependabot, OWASP Dependency-Check).

IaC scanner not in pipeline

Controls violated: A.8.9, A.8.27. Detection: As above, for IaC scanning (Checkov, tfsec, Terrascan).

Secret scanning not in pipeline

Controls violated: A.8.24, A.5.17. Detection: As above, for secret scanning (gitleaks, truffleHog, GitHub native secret scanning).

No environment separation

Controls violated: A.8.31 (Separation of dev/test/prod). Pattern: Single Terraform state file or single AWS account hosting both staging and production resources. Detection: Workspace / state file inspection. Account ID checks across environment-specific variable files.

Auto-merge bypassing review

Controls violated: A.8.4, A.8.32. Pattern: GitHub auto-merge enabled on PRs without required reviewers, or CODEOWNERS not enforced. Detection: Repository settings via Steampipe or GitHub API.