Add attack surface audit artifacts
Some checks failed
CI / Validate (pull_request) Has been cancelled
Some checks failed
CI / Validate (pull_request) Has been cancelled
- Add advisory, entrypoint, and candidate scan outputs - Capture dependency intelligence and cross-service attack surface notes
This commit is contained in:
parent
a35a757622
commit
47a5adca90
26 changed files with 2807 additions and 0 deletions
153
piolium/attack-surface/candidates-summary.md
Normal file
153
piolium/attack-surface/candidates-summary.md
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
# Candidate Scan
|
||||
|
||||
Generated by piolium at 2026-05-27T05:18:10.316Z
|
||||
|
||||
## Totals
|
||||
|
||||
- Files scanned: 189
|
||||
- Candidate files: 45
|
||||
- Candidate matches: 289
|
||||
- Per-file records: disabled (set PIOLIUM_FILE_RECORDS=1 to enable)
|
||||
|
||||
## Candidate Classes
|
||||
|
||||
- secret-literal: 2 match(es), max score 114. Hardcoded secret-like literal.
|
||||
- dynamic-code-execution: 20 match(es), max score 90. Dynamic code execution, expression evaluation, or runtime compilation.
|
||||
- command-execution: 34 match(es), max score 80. Potential command execution or shell invocation with variable input.
|
||||
- hidden-control-channel: 40 match(es), max score 71. Request header or framework/proxy context read that may influence auth, routing, tenant, runtime, debug, or middleware behavior.
|
||||
- ssrf-capable-request: 25 match(es), max score 71. Outbound HTTP request site that may be attacker-controlled.
|
||||
- open-redirect: 4 match(es), max score 65. Redirect sink that may accept user-controlled URLs.
|
||||
- unsafe-html-or-template: 4 match(es), max score 63. HTML injection sink or template escape bypass.
|
||||
- path-traversal-file-access: 99 match(es), max score 55. Filesystem access using path joins or user-controllable paths.
|
||||
- raw-sql-query: 21 match(es), max score 55. Raw SQL construction or query execution that may need parameterization review.
|
||||
- public-entrypoint: 40 match(es), max score 54. Public route, handler, controller, workflow, or operation entry point.
|
||||
|
||||
## Top Files
|
||||
|
||||
- `packages/storage/src/clickhouse.ts`: score 4755, 69 match(es)
|
||||
- `apps/web/app/terminal.tsx`: score 2040, 38 match(es)
|
||||
- `scripts/deploy.ts`: score 1795, 29 match(es)
|
||||
- `services/api/src/index.ts`: score 949, 23 match(es)
|
||||
- `scripts/dev.ts`: score 905, 16 match(es)
|
||||
- `scripts/check-docker-workspace.ts`: score 605, 11 match(es)
|
||||
- `scripts/dev-desktop.ts`: score 520, 9 match(es)
|
||||
- `scripts/dev-services.ts`: score 355, 6 match(es)
|
||||
- `services/api/src/live.ts`: score 316, 7 match(es)
|
||||
- `scripts/check-public-api-routes.ts`: score 305, 5 match(es)
|
||||
- `packages/bus/src/jetstream.ts`: score 275, 5 match(es)
|
||||
- `services/compute/src/structure-packets.ts`: score 275, 5 match(es)
|
||||
- `services/ingest-options/src/adapters/ibkr.ts`: score 245, 4 match(es)
|
||||
- `services/api/src/option-queries.ts`: score 228, 6 match(es)
|
||||
- `services/compute/src/index.ts`: score 225, 3 match(es)
|
||||
- `apps/desktop/src/security.ts`: score 220, 4 match(es)
|
||||
- `scripts/sync-docker-workspace.ts`: score 220, 4 match(es)
|
||||
- `apps/web/app/api/admin/synthetic/shared.ts`: score 188, 3 match(es)
|
||||
- `services/candles/src/index.ts`: score 170, 2 match(es)
|
||||
- `services/compute/src/rolling-stats.ts`: score 170, 2 match(es)
|
||||
- `services/ingest-news/src/symbols.ts`: score 170, 2 match(es)
|
||||
- `apps/web/app/api/admin/synthetic/routes.test.ts`: score 168, 2 match(es)
|
||||
- `apps/desktop/src/security.test.ts`: score 110, 2 match(es)
|
||||
- `packages/config/src/env.ts`: score 110, 2 match(es)
|
||||
- `packages/types/src/live.ts`: score 110, 2 match(es)
|
||||
- `packages/types/src/options-flow.ts`: score 110, 2 match(es)
|
||||
- `services/compute/src/contracts.ts`: score 110, 2 match(es)
|
||||
- `services/ingest-equities/src/adapters/alpaca.ts`: score 110, 2 match(es)
|
||||
- `services/ingest-options/py/databento_replay.py`: score 110, 2 match(es)
|
||||
- `services/ingest-options/py/ibkr_stream.py`: score 110, 2 match(es)
|
||||
- `services/replay/src/index.ts`: score 110, 2 match(es)
|
||||
- `apps/web/app/terminal.test.ts`: score 90, 3 match(es)
|
||||
- `packages/config/tests/alpaca.test.ts`: score 90, 1 match(es)
|
||||
- `apps/web/scripts/dev.ts`: score 80, 1 match(es)
|
||||
- `services/ingest-options/src/adapters/databento.ts`: score 80, 1 match(es)
|
||||
- `apps/web/app/charts/page.tsx`: score 65, 1 match(es)
|
||||
- `apps/web/app/replay/page.tsx`: score 65, 1 match(es)
|
||||
- `apps/web/app/signals/page.tsx`: score 65, 1 match(es)
|
||||
- `apps/web/app/tape/page.tsx`: score 65, 1 match(es)
|
||||
- `apps/web/app/frontend-cooker/page.tsx`: score 55, 1 match(es)
|
||||
|
||||
## Highest-Ranked Matches
|
||||
|
||||
- secret-literal (precise, score 114) at `apps/web/app/api/admin/synthetic/routes.test.ts:28` - token: "secret-token"
|
||||
- secret-literal (precise, score 90) at `packages/config/tests/alpaca.test.ts:60` - secret: "short-secret",
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:118` - exec(params: { query: string }): Promise<void>;
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:189` - async exec({ query }) {
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:243` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:247` - await client.exec({ query });
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:254` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:262` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:270` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:278` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:286` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:294` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:302` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:310` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:318` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:324` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:328` - await client.exec({ query });
|
||||
- dynamic-code-execution (precise, score 90) at `packages/storage/src/clickhouse.ts:333` - await client.exec({
|
||||
- dynamic-code-execution (precise, score 90) at `services/candles/src/index.ts:156` - await multi.exec();
|
||||
- dynamic-code-execution (precise, score 90) at `services/compute/src/index.ts:351` - const match = SYNTHETIC_EVENT_CONDITION_RE.exec(condition);
|
||||
- dynamic-code-execution (precise, score 90) at `services/compute/src/rolling-stats.ts:163` - await multi.exec();
|
||||
- dynamic-code-execution (precise, score 90) at `services/ingest-news/src/symbols.ts:27` - while ((match = regex.exec(value)) !== null) {
|
||||
- command-execution (precise, score 80) at `apps/web/scripts/dev.ts:16` - const child = Bun.spawn(["next", "dev", "-p", String(port)], {
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:118` - exec(params: { query: string }): Promise<void>;
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:189` - async exec({ query }) {
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:243` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:247` - await client.exec({ query });
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:254` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:262` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:270` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:278` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:286` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:294` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:302` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:310` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:318` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:324` - await client.exec({
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:328` - await client.exec({ query });
|
||||
- command-execution (precise, score 80) at `packages/storage/src/clickhouse.ts:333` - await client.exec({
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:180` - const result = spawnSync(command, args, {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:196` - const result = spawnSync(command, args, {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:216` - const result = spawnSync(command, args, {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:238` - const result = spawnSync("bash", localArgs, {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:253` - const result = spawnSync("ssh", sshArgs, {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:402` - return spawnSync("git", ["remote", "get-url", name], {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:581` - const result = spawnSync("bun", ["run", "check:docker-workspace"], {
|
||||
- command-execution (precise, score 80) at `scripts/deploy.ts:670` - const upstreamResult = spawnSync(
|
||||
- command-execution (precise, score 80) at `scripts/dev-desktop.ts:137` - const proc = Bun.spawn(cmd, {
|
||||
- command-execution (precise, score 80) at `scripts/dev-services.ts:136` - const proc = Bun.spawn(cmd, {
|
||||
- command-execution (precise, score 80) at `scripts/dev.ts:189` - const proc = Bun.spawn(cmd, {
|
||||
- command-execution (precise, score 80) at `services/candles/src/index.ts:156` - await multi.exec();
|
||||
- command-execution (precise, score 80) at `services/compute/src/index.ts:351` - const match = SYNTHETIC_EVENT_CONDITION_RE.exec(condition);
|
||||
- command-execution (precise, score 80) at `services/compute/src/rolling-stats.ts:163` - await multi.exec();
|
||||
- command-execution (precise, score 80) at `services/ingest-news/src/symbols.ts:27` - while ((match = regex.exec(value)) !== null) {
|
||||
- command-execution (precise, score 80) at `services/ingest-options/src/adapters/databento.ts:305` - const child = Bun.spawn(buildArgs(trimmed), {
|
||||
- command-execution (precise, score 80) at `services/ingest-options/src/adapters/ibkr.ts:92` - const child = Bun.spawn(args, {
|
||||
- ssrf-capable-request (normal, score 71) at `apps/web/app/api/admin/synthetic/shared.ts:51` - const response = await fetch(url.toString(), {
|
||||
- hidden-control-channel (normal, score 71) at `apps/web/app/api/admin/synthetic/shared.ts:60` - "content-type": response.headers.get("content-type") ?? "application/json"
|
||||
- hidden-control-channel (normal, score 71) at `scripts/check-public-api-routes.ts:20` - return (response.headers.get("content-type") ?? "").toLowerCase().includes("application/json");
|
||||
- ssrf-capable-request (normal, score 71) at `scripts/check-public-api-routes.ts:25` - const response = await fetch(url);
|
||||
- hidden-control-channel (normal, score 71) at `scripts/check-public-api-routes.ts:34` - throw new Error(`${url.pathname} returned non-JSON content (${response.headers.get("content-type") ?? "none"}): ${sample}`);
|
||||
- open-redirect (normal, score 65) at `apps/web/app/charts/page.tsx:6` - redirect("/");
|
||||
- open-redirect (normal, score 65) at `apps/web/app/replay/page.tsx:6` - redirect("/");
|
||||
- open-redirect (normal, score 65) at `apps/web/app/signals/page.tsx:6` - redirect("/");
|
||||
- open-redirect (normal, score 65) at `apps/web/app/tape/page.tsx:6` - redirect("/options");
|
||||
- hidden-control-channel (normal, score 63) at `services/api/src/index.ts:328` - const authorization = req.headers.get("authorization") ?? "";
|
||||
- hidden-control-channel (normal, score 63) at `services/api/src/index.ts:332` - return req.headers.get("x-synthetic-admin-token")?.trim() ?? "";
|
||||
- hidden-control-channel (normal, score 63) at `services/api/src/index.ts:2052` - logger.info("api listening", { host: env.API_HOST, port: server.port });
|
||||
- unsafe-html-or-template (normal, score 63) at `services/api/src/live.ts:142` - console.warn(`Invalid ${key}="${raw}", using ${fallback}`);
|
||||
- unsafe-html-or-template (normal, score 63) at `services/api/src/live.ts:161` - console.warn(`Invalid LIVE_LIMIT_DEFAULT="${raw}", using ${fallback}`);
|
||||
- hidden-control-channel (normal, score 55) at `apps/desktop/src/security.test.ts:11` - it("allows the hosted production origin on /options", () => {
|
||||
- hidden-control-channel (normal, score 55) at `apps/desktop/src/security.test.ts:15` - it("keeps /tape trusted as a compatibility path on the same origin", () => {
|
||||
- hidden-control-channel (normal, score 55) at `apps/desktop/src/security.ts:5` - new URL(DESKTOP_PRODUCTION_URL).origin,
|
||||
- hidden-control-channel (normal, score 55) at `apps/desktop/src/security.ts:6` - new URL(DESKTOP_LOCAL_DEV_URL).origin,
|
||||
- hidden-control-channel (normal, score 55) at `apps/desktop/src/security.ts:26` - return TRUSTED_ORIGINS.has(url.origin);
|
||||
- hidden-control-channel (normal, score 55) at `apps/desktop/src/security.ts:35` - return !TRUSTED_ORIGINS.has(url.origin);
|
||||
- path-traversal-file-access (normal, score 55) at `apps/web/app/frontend-cooker/page.tsx:43` - <section className={styles.tableWrap}><table><thead><tr>{["Ticker", "Contract", "Expiry", "Notional", "Side", "Delta", "Condition"].map(h => <th key={h}>{h}</th>)}</tr></thead><tbody>{flowRows.map((r) => <tr key={r.join(
|
||||
- hidden-control-channel (normal, score 55) at `apps/web/app/terminal.tsx:516` - const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
|
||||
- hidden-control-channel (normal, score 55) at `apps/web/app/terminal.tsx:1024` - const host = isLocal ? `${hostname}:4000` : window.location.host;
|
||||
- hidden-control-channel (normal, score 55) at `apps/web/app/terminal.tsx:1024` - const host = isLocal ? `${hostname}:4000` : window.location.host;
|
||||
|
||||
## Custom Matchers
|
||||
|
||||
Project matchers can be added at `piolium/matchers.json`, `piolium/custom-matchers.json`, or `.piolium-matchers.json`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue