Skip to content

fix(security): CodeQL icons literals + pnpm overrides for advisories#40

Merged
sraphaz merged 6 commits into
mainfrom
fix/security-codeql-deps-summary
Apr 2, 2026
Merged

fix(security): CodeQL icons literals + pnpm overrides for advisories#40
sraphaz merged 6 commits into
mainfrom
fix/security-codeql-deps-summary

Conversation

@sraphaz

@sraphaz sraphaz commented Apr 2, 2026

Copy link
Copy Markdown
Owner

Goal

Clear and prevent GitHub security alerts on this repository: Dependabot (transitive npm advisories in pnpm-lock.yaml) and Code scanning (CodeQL: unsafe string embedding in generated code, workflow TOCTOU, missing explicit permissions).

Security & supply chain

  • packages/vite-plugin: hardenJsonStringLiteralForEmbeddedScript (+ tests), applied across virtual codegen sinks (icons, _shared / generateCombinedProjects, single-project, mmd) so dynamic import() and embedded JSON literals satisfy CodeQL bad code sanitization expectations.
  • Root package.json: pnpm.overrides raising floors for vulnerable transitives (e.g. lodash / lodash-es, path-to-regexp, picomatch, brace-expansion, bn.js, yaml, smol-toml, ajv, pbkdf2, sha.js, qs, min-document, diff, …).
  • pnpm-lock.yaml: updated to match overrides.

GitHub Actions & Code scanning

  • codeql.yml: analysis for likec4/likec4 and sraphaz/likec4; workflow_dispatch for manual runs on the fork.
  • issue-comment.yaml: checkout PR head.sha from the API (immutable) + persist-credentials: false — mitigates Untrusted checkout TOCTOU.
  • checks.yaml: workflow default contents: read; actions: write only on jobs that upload or download artifacts (check-build, check-e2e-tests, check-e2e-types) — least privilege while keeping artifact steps working (CodeRabbit’s “drop actions: write” globally would break uploads).
  • ci-pr.yaml / push.yaml / pkg-pr-new.yaml / trigger-deploy-template.yaml: explicit top-level permissions where required for callers or standalone workflows.

Chores

  • .gitignore: local .gh-pr-*.md drafts.

Changesets

  • .changeset/security-icons-codeql-lockfile.md — patch bump for likec4 (security hardening).

Verification

  • pnpm typecheck / pnpm test (local)
  • Code scanning / Dependabot re-evaluated after merge (or Actions → codeql → Run workflow)

@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds documentation for LeanIX ↔ Draw.io bridge workflows and MCP scope, introduces a utility to harden JSON string literals used in vite-plugin virtuals (with tests and integration), and updates root pnpm.overrides and CI workflow permissions and gitignore patterns.

Changes

Cohort / File(s) Summary
Documentation & Changesets
.changeset/leanix-bridge-skills-mcp-docs.md, .changeset/security-icons-codeql-lockfile.md, AGENTS.md, packages/mcp/README.md, skills/likec4-dsl/SKILL.md, skills/likec4-dsl/references/cli.md, skills/likec4-dsl/references/bridge-leanix-drawio.md
Added changesets; updated AGENTS and MCP README to clarify MCP scope; added CLI guidance and a new comprehensive LeanIX+Draw.io bridge reference describing commands, profiles (--profile leanix), round-trip mapping, and config expectations.
vite-plugin: hardening & tests
packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.ts, packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.spec.ts, packages/vite-plugin/src/virtuals/icons.ts
New exported function to escape script-breakout characters in JSON-stringified literals; unit tests covering multiple edge cases; integrated hardening into icons virtual module for embedded project ids and dynamic import literals.
Tooling & CI
package.json, .gitignore, .github/workflows/...
Added extensive pnpm.overrides to raise dependency security floors and pin transitive versions; ignored .gh-pr-*.md in .gitignore; added explicit permissions and minor trigger/quoting changes across several GitHub Actions workflows and updated preview job ref handling.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer (CLI)
    participant CLI as likec4 CLI
    participant MCP as MCP Server / likec4:mcp
    participant LeanIX as LeanIX API
    participant Drawio as Draw.io

    Dev->>CLI: bunx likec4 gen leanix --dry-run
    CLI->>CLI: produce LeanIX manifest (with likec4 IDs)
    Dev->>CLI: bunx likec4 sync leanix --dry-run / --apply (with LEANIX_API_TOKEN)
    CLI->>LeanIX: sync manifest (dry-run/apply)
    Dev->>CLI: bunx likec4 export --profile leanix --to drawio
    CLI->>Drawio: export Draw.io XML (bridge-managed ids)
    Dev->>CLI: bunx likec4 parse drawio (round-trip)
    CLI->>CLI: manifestToDrawioLeanixMapping(manifest) -> map identifiers
    Dev->>MCP: likec4 mcp (query/search)  // read-only model access
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I nibble at strings and hop with glee,
I tuck each < and / safe as can be.
Bridges and manifests stitched in a row,
Draw.io and LeanIX — onward we go!
🌿 A tiny rabbit, keeping code tidy and free.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(security): CodeQL icons literals + pnpm overrides for advisories' clearly and concisely summarizes the main security-focused changes: hardening CodeQL icon handling and dependency override management.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed PR description is comprehensive and detailed, covering security goals, implementation details, GitHub Actions changes, and verification status.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/security-codeql-deps-summary

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.ts (1)

9-16: Optional: add a contract guard to catch accidental non-JSON-literal inputs.

A tiny precondition can prevent misuse in future call sites.

Suggested defensive check
 export function hardenJsonStringLiteralForEmbeddedScript(jsonStringified: string): string {
+  if (!(jsonStringified.startsWith('"') && jsonStringified.endsWith('"'))) {
+    throw new Error('Expected a JSON.stringify(...) string literal input')
+  }
   return jsonStringified
     .replace(/</g, '\\u003C')
     .replace(/>/g, '\\u003E')
     .replace(/\//g, '\\u002F')
     .replace(/\u2028/g, '\\u2028')
     .replace(/\u2029/g, '\\u2029')
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.ts`
around lines 9 - 16, Add a defensive contract guard to
hardenJsonStringLiteralForEmbeddedScript: verify the input is a string (typeof
jsonStringified === 'string') and sanity-check that it looks like a JSON literal
(e.g. starts with '"', '{', '[' or matches /^-?\d|^(true|false|null)/); if the
check fails throw a clear TypeError mentioning
hardenJsonStringLiteralForEmbeddedScript so misuse is caught early. This keeps
the existing replacements but prevents accidental non-JSON-literal inputs from
being silently processed.
packages/vite-plugin/src/virtuals/icons.ts (1)

101-109: Recommended follow-up: apply the same hardening to other virtual codegen sinks.

You still have direct JSON.stringify(...) embedding in:

  • packages/vite-plugin/src/virtuals/_shared.ts (lines 88-93),
  • packages/vite-plugin/src/virtuals/single-project.ts (lines 4-14),
  • packages/vite-plugin/src/virtuals/mmd.ts (lines 26-30).

Using the same helper there would make this mitigation consistent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vite-plugin/src/virtuals/icons.ts` around lines 101 - 109, Other
virtual codegen sinks still embed JSON via direct JSON.stringify; update them to
use the same hardening helper as used here: replace JSON.stringify(...)
embeddings with
hardenJsonStringLiteralForEmbeddedScript(embed...AsJsString(...)) calls (reusing
embedProjectIdAsJsString/embedUrlAsJsString where appropriate) so the generated
literals are hardened before injecting into code; check the virtual generators
mentioned (virtuals/_shared.ts, virtuals/single-project.ts, virtuals/mmd.ts) and
swap the raw JSON.stringify usages for hardenJsonStringLiteralForEmbeddedScript
wrapping the corresponding embed*AsJsString helpers, keeping the import usage
consistent with joinURL and IconRenderer patterns already used in icons.ts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.ts`:
- Around line 9-16: Add a defensive contract guard to
hardenJsonStringLiteralForEmbeddedScript: verify the input is a string (typeof
jsonStringified === 'string') and sanity-check that it looks like a JSON literal
(e.g. starts with '"', '{', '[' or matches /^-?\d|^(true|false|null)/); if the
check fails throw a clear TypeError mentioning
hardenJsonStringLiteralForEmbeddedScript so misuse is caught early. This keeps
the existing replacements but prevents accidental non-JSON-literal inputs from
being silently processed.

In `@packages/vite-plugin/src/virtuals/icons.ts`:
- Around line 101-109: Other virtual codegen sinks still embed JSON via direct
JSON.stringify; update them to use the same hardening helper as used here:
replace JSON.stringify(...) embeddings with
hardenJsonStringLiteralForEmbeddedScript(embed...AsJsString(...)) calls (reusing
embedProjectIdAsJsString/embedUrlAsJsString where appropriate) so the generated
literals are hardened before injecting into code; check the virtual generators
mentioned (virtuals/_shared.ts, virtuals/single-project.ts, virtuals/mmd.ts) and
swap the raw JSON.stringify usages for hardenJsonStringLiteralForEmbeddedScript
wrapping the corresponding embed*AsJsString helpers, keeping the import usage
consistent with joinURL and IconRenderer patterns already used in icons.ts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c67d3164-316d-4170-a5f5-8eba30071897

📥 Commits

Reviewing files that changed from the base of the PR and between 0a4af22 and 8c6438e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • .changeset/leanix-bridge-skills-mcp-docs.md
  • .changeset/security-icons-codeql-lockfile.md
  • .gitignore
  • AGENTS.md
  • package.json
  • packages/mcp/README.md
  • packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.spec.ts
  • packages/vite-plugin/src/virtuals/hardenJsonStringLiteralForEmbeddedScript.ts
  • packages/vite-plugin/src/virtuals/icons.ts
  • skills/likec4-dsl/SKILL.md
  • skills/likec4-dsl/references/bridge-leanix-drawio.md
  • skills/likec4-dsl/references/cli.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/checks.yaml:
- Around line 6-9: Remove the unnecessary actions: write permission from the
workflow permissions block; keep contents: read for actions/checkout, and ensure
that artifact steps (actions/upload-artifact@v6, actions/download-artifact@v7)
and external Cloudflare Wrangler use their existing tokens/APIs without
requiring actions: write—so delete the line containing "actions: write" in the
permissions block to enforce least privilege.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4babd49-8763-449b-aadc-931a1c674ffa

📥 Commits

Reviewing files that changed from the base of the PR and between 8c6438e and 4e30b3b.

📒 Files selected for processing (7)
  • .github/workflows/checks.yaml
  • .github/workflows/ci-pr.yaml
  • .github/workflows/codeql.yml
  • .github/workflows/issue-comment.yaml
  • .github/workflows/pkg-pr-new.yaml
  • .github/workflows/push.yaml
  • .github/workflows/trigger-deploy-template.yaml
✅ Files skipped from review due to trivial changes (3)
  • .github/workflows/push.yaml
  • .github/workflows/trigger-deploy-template.yaml
  • .github/workflows/ci-pr.yaml

Comment on lines +6 to +9
permissions:
contents: read
actions: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if any step in this workflow or called actions use GitHub Actions API endpoints requiring write access

# Look for any cancel, re-run, or workflow management operations
rg -n 'cancel|re-run|workflow.*run|actions/stale' .github/workflows/checks.yaml

# Check if turbo or any tooling might need actions:write for caching
rg -n 'cache|turbo' .github/workflows/checks.yaml

# Check if the bootstrap action might require actions:write
cat .github/actions/bootstrap/action.yaml 2>/dev/null || cat .github/actions/bootstrap/action.yml 2>/dev/null

Repository: sraphaz/likec4

Length of output: 1032


🏁 Script executed:

cat -n .github/workflows/checks.yaml | head -250

Repository: sraphaz/likec4

Length of output: 7668


Remove the unnecessary actions: write permission.

The contents: read permission is required for actions/checkout. However, actions: write is not used anywhere in this workflow. The artifact upload/download operations (actions/upload-artifact@v6, actions/download-artifact@v7) use the built-in artifacts API and do not require this permission. The Cloudflare Wrangler action uses an external API token, and the conditional !cancelled() check is purely informational. Removing this permission follows the principle of least privilege:

Suggested change
 permissions:
   contents: read
-  actions: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
actions: write
permissions:
contents: read
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/checks.yaml around lines 6 - 9, Remove the unnecessary
actions: write permission from the workflow permissions block; keep contents:
read for actions/checkout, and ensure that artifact steps
(actions/upload-artifact@v6, actions/download-artifact@v7) and external
Cloudflare Wrangler use their existing tokens/APIs without requiring actions:
write—so delete the line containing "actions: write" in the permissions block to
enforce least privilege.

sraphaz added 6 commits April 2, 2026 01:31
Apply uncle-bob boundary: one policy surface (root overrides) plus small harden helper + tests.

pnpm audit: only elliptic (GHSA-848j) remains — no patched release on npm (<0.0.0).

Made-with: Cursor
@sraphaz sraphaz force-pushed the fix/security-codeql-deps-summary branch from 7db2b81 to 01ca65b Compare April 2, 2026 04:32
@sraphaz sraphaz merged commit a52773c into main Apr 2, 2026
7 checks passed
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