circle-ir 3.168.0 → 3.174.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/configs/sinks/prompt_injection.yaml +50 -0
  2. package/dist/analysis/config-loader.d.ts.map +1 -1
  3. package/dist/analysis/config-loader.js +157 -0
  4. package/dist/analysis/config-loader.js.map +1 -1
  5. package/dist/analysis/passes/cross-file-pass.d.ts.map +1 -1
  6. package/dist/analysis/passes/cross-file-pass.js +3 -2
  7. package/dist/analysis/passes/cross-file-pass.js.map +1 -1
  8. package/dist/analysis/passes/interprocedural-pass.d.ts.map +1 -1
  9. package/dist/analysis/passes/interprocedural-pass.js +3 -2
  10. package/dist/analysis/passes/interprocedural-pass.js.map +1 -1
  11. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  12. package/dist/analysis/passes/sink-filter-pass.js +2 -1
  13. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  14. package/dist/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
  15. package/dist/analysis/passes/taint-propagation-pass.js +29 -15
  16. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  17. package/dist/analysis/rules.d.ts.map +1 -1
  18. package/dist/analysis/rules.js +9 -0
  19. package/dist/analysis/rules.js.map +1 -1
  20. package/dist/analysis/sanitizer-index.d.ts +34 -0
  21. package/dist/analysis/sanitizer-index.d.ts.map +1 -0
  22. package/dist/analysis/sanitizer-index.js +48 -0
  23. package/dist/analysis/sanitizer-index.js.map +1 -0
  24. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  25. package/dist/analysis/taint-matcher.js +93 -45
  26. package/dist/analysis/taint-matcher.js.map +1 -1
  27. package/dist/analysis/taint-propagation.d.ts.map +1 -1
  28. package/dist/analysis/taint-propagation.js +5 -2
  29. package/dist/analysis/taint-propagation.js.map +1 -1
  30. package/dist/analyzer.d.ts.map +1 -1
  31. package/dist/analyzer.js +51 -2
  32. package/dist/analyzer.js.map +1 -1
  33. package/dist/browser/circle-ir.js +336 -95
  34. package/dist/core/circle-ir-core.cjs +272 -73
  35. package/dist/core/circle-ir-core.js +272 -73
  36. package/dist/core/extractors/cfg.d.ts +11 -1
  37. package/dist/core/extractors/cfg.d.ts.map +1 -1
  38. package/dist/core/extractors/cfg.js +18 -9
  39. package/dist/core/extractors/cfg.js.map +1 -1
  40. package/dist/core/extractors/imports.d.ts +9 -1
  41. package/dist/core/extractors/imports.d.ts.map +1 -1
  42. package/dist/core/extractors/imports.js +29 -22
  43. package/dist/core/extractors/imports.js.map +1 -1
  44. package/dist/types/index.d.ts +1 -1
  45. package/dist/types/index.d.ts.map +1 -1
  46. package/package.json +1 -1
@@ -0,0 +1,50 @@
1
+ {
2
+ "$comment": "Reference-only. Runtime uses DEFAULT_SINKS in src/analysis/config-loader.ts. See cognium-dev#248.",
3
+ "sinks": [
4
+ { "method": "create", "class": "Completions", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
5
+ { "method": "create", "class": "Responses", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
6
+ { "method": "create", "class": "ChatCompletion", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
7
+ { "method": "create", "class": "Completion", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
8
+ { "method": "create", "class": "Messages", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
9
+ { "method": "stream", "class": "Messages", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
10
+ { "method": "completion", "class": "litellm", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
11
+ { "method": "acompletion", "class": "litellm", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
12
+ { "method": "invoke", "class": "ChatOpenAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
13
+ { "method": "predict", "class": "ChatOpenAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
14
+ { "method": "stream", "class": "ChatOpenAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
15
+ { "method": "generate", "class": "ChatOpenAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
16
+ { "method": "invoke", "class": "ChatAnthropic", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
17
+ { "method": "invoke", "class": "ChatGoogleGenerativeAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
18
+ { "method": "run", "class": "LLMChain", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
19
+ { "method": "invoke", "class": "LLMChain", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["python"] },
20
+
21
+ { "method": "create", "class": "Completions", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
22
+ { "method": "create", "class": "Responses", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
23
+ { "method": "create", "class": "Messages", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
24
+ { "method": "stream", "class": "Messages", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
25
+ { "method": "generateText", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0], "languages": ["javascript", "typescript"] },
26
+ { "method": "streamText", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0], "languages": ["javascript", "typescript"] },
27
+ { "method": "generateObject", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0], "languages": ["javascript", "typescript"] },
28
+ { "method": "streamObject", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0], "languages": ["javascript", "typescript"] },
29
+ { "method": "invoke", "class": "ChatOpenAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
30
+ { "method": "invoke", "class": "ChatAnthropic", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
31
+ { "method": "stream", "class": "ChatOpenAI", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["javascript", "typescript"] },
32
+
33
+ { "method": "generate", "class": "ChatLanguageModel", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
34
+ { "method": "chat", "class": "ChatLanguageModel", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
35
+ { "method": "generate", "class": "StreamingChatLanguageModel", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
36
+ { "method": "chat", "class": "StreamingChatLanguageModel", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
37
+ { "method": "prompt", "class": "ChatClient", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
38
+ { "method": "call", "class": "ChatClient", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
39
+ { "method": "call", "class": "ChatModel", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
40
+ { "method": "createChatCompletion", "class": "OpenAiService", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
41
+ { "method": "createCompletion", "class": "OpenAiService", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["java"] },
42
+
43
+ { "method": "CreateChatCompletion", "class": "Client", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["go"] },
44
+ { "method": "CreateCompletion", "class": "Client", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["go"] },
45
+ { "method": "CreateChatCompletionStream", "class": "Client", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["go"] },
46
+ { "method": "Call", "class": "LLM", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["go"] },
47
+ { "method": "Generate", "class": "LLM", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["go"] },
48
+ { "method": "GenerateContent", "class": "Model", "type": "prompt_injection", "cwe": "CWE-1427", "severity": "high", "arg_positions": [0, 1, 2, 3], "languages": ["go"] }
49
+ ]
50
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,mBAAmB,EAAE,GAC7B,kBAAkB,EAAE,CAQtB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,qBAAqB,GAAE,MAAM,EAAO,GACnC,WAAW,CAYb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAoc1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EAioDtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAwThD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,EAiDtD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAO9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,mBAAmB,EAAE,GAC7B,kBAAkB,EAAE,CAQtB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,qBAAqB,GAAE,MAAM,EAAO,GACnC,WAAW,CAYb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA6hB1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EA6tDtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAwThD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,EAiDtD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAO9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
@@ -475,6 +475,85 @@ export const DEFAULT_SOURCES = [
475
475
  { method: 'read', class: 'TcpStream', type: 'network_input', severity: 'high', return_tainted: true },
476
476
  { method: 'read_to_end', class: 'TcpStream', type: 'network_input', severity: 'high', return_tainted: true },
477
477
  { method: 'read_to_string', class: 'TcpStream', type: 'network_input', severity: 'high', return_tainted: true },
478
+ // =========================================================================
479
+ // Modern taint sources (cognium-dev #242 — 3.170.0)
480
+ // GraphQL resolver args, gRPC request metadata, cache reads (second-order
481
+ // taint), and JWT claims (unverified decode). These attacker-influenced
482
+ // surfaces were previously silent — a resolver that concatenated an
483
+ // `Args`-annotated field into a SQL string produced zero flows.
484
+ // =========================================================================
485
+ // --- GraphQL resolver argument sources (JS / TS — Apollo, TypeGraphQL, NestJS) ---
486
+ // TypeGraphQL / NestJS annotate query/mutation/subscription methods; every
487
+ // parameter on the annotated method carries attacker input from the GraphQL
488
+ // POST body's `variables` field.
489
+ { method_annotation: 'Query', type: 'http_body', severity: 'high', languages: ['javascript', 'typescript'] },
490
+ { method_annotation: 'Mutation', type: 'http_body', severity: 'high', languages: ['javascript', 'typescript'] },
491
+ { method_annotation: 'Subscription', type: 'http_body', severity: 'high', languages: ['javascript', 'typescript'] },
492
+ { method_annotation: 'FieldResolver', type: 'http_body', severity: 'high', languages: ['javascript', 'typescript'] },
493
+ { method_annotation: 'ResolveField', type: 'http_body', severity: 'high', languages: ['javascript', 'typescript'] },
494
+ // Parameter-level: `@Arg('id') id: string`, `@Args('input') input: FooDto`.
495
+ { annotation: 'Arg', type: 'http_param', severity: 'high', param_tainted: true, languages: ['javascript', 'typescript'] },
496
+ { annotation: 'Args', type: 'http_param', severity: 'high', param_tainted: true, languages: ['javascript', 'typescript'] },
497
+ // --- GraphQL resolver argument sources (Python — Strawberry, Graphene, Ariadne) ---
498
+ { method_annotation: 'strawberry.field', type: 'http_body', severity: 'high', languages: ['python'] },
499
+ { method_annotation: 'strawberry.mutation', type: 'http_body', severity: 'high', languages: ['python'] },
500
+ { method_annotation: 'strawberry.subscription', type: 'http_body', severity: 'high', languages: ['python'] },
501
+ // --- GraphQL resolver argument sources (Java — Netflix DGS, SPQR, graphql-java-annotations) ---
502
+ { method_annotation: 'DgsQuery', type: 'http_body', severity: 'high', languages: ['java'] },
503
+ { method_annotation: 'DgsMutation', type: 'http_body', severity: 'high', languages: ['java'] },
504
+ { method_annotation: 'DgsSubscription', type: 'http_body', severity: 'high', languages: ['java'] },
505
+ { method_annotation: 'DgsData', type: 'http_body', severity: 'high', languages: ['java'] },
506
+ { method_annotation: 'GraphQLQuery', type: 'http_body', severity: 'high', languages: ['java'] },
507
+ { method_annotation: 'GraphQLMutation', type: 'http_body', severity: 'high', languages: ['java'] },
508
+ { annotation: 'InputArgument', type: 'http_param', severity: 'high', param_tainted: true, languages: ['java'] },
509
+ { annotation: 'GraphQLArgument', type: 'http_param', severity: 'high', param_tainted: true, languages: ['java'] },
510
+ // --- gRPC request metadata (Python — grpcio) ---
511
+ // `context.invocation_metadata()` returns the caller-supplied metadata tuple.
512
+ // No `class` filter — receiver names vary (`context`, `ctx`, `servicer_context`).
513
+ { method: 'invocation_metadata', type: 'http_header', severity: 'high', return_tainted: true, languages: ['python'] },
514
+ // --- gRPC request metadata (JS / TS — @grpc/grpc-js) ---
515
+ // `call.metadata.get(key)` / `call.metadata.getMap()` inside a service handler.
516
+ { method: 'get', class: 'Metadata', type: 'http_header', severity: 'high', return_tainted: true, languages: ['javascript', 'typescript'] },
517
+ { method: 'getMap', class: 'Metadata', type: 'http_header', severity: 'high', return_tainted: true, languages: ['javascript', 'typescript'] },
518
+ // --- gRPC request metadata (Go — google.golang.org/grpc/metadata) ---
519
+ // `md, _ := metadata.FromIncomingContext(ctx)` pulls the caller's headers.
520
+ { method: 'FromIncomingContext', class: 'metadata', type: 'http_header', severity: 'high', return_tainted: true, languages: ['go'] },
521
+ // --- gRPC request metadata (Java — io.grpc.Metadata) ---
522
+ // Server-side interceptor receives `Metadata headers`; `headers.get(KEY)`
523
+ // returns caller-supplied header values.
524
+ { method: 'get', class: 'Metadata', type: 'http_header', severity: 'high', return_tainted: true, languages: ['java'] },
525
+ // --- Cache reads (second-order taint — Redis / Memcached / Django cache) ---
526
+ // The cache round-trip is a canonical second-order sink: whatever was
527
+ // written previously (potentially attacker-controlled) resurfaces on read.
528
+ // Severity 'medium' — cache contents are usually filtered by the writer but
529
+ // the read side often forgets that guarantee. Class-scoped to `Redis`,
530
+ // `Jedis`, `cache` to avoid colliding with generic `Map.get()`.
531
+ { method: 'get', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['python'] },
532
+ { method: 'hget', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['python'] },
533
+ { method: 'mget', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['python'] },
534
+ { method: 'lrange', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['python'] },
535
+ { method: 'get', class: 'cache', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['python'] },
536
+ { method: 'get_many', class: 'cache', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['python'] },
537
+ { method: 'get', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['javascript', 'typescript'] },
538
+ { method: 'hget', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['javascript', 'typescript'] },
539
+ { method: 'mget', class: 'Redis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['javascript', 'typescript'] },
540
+ { method: 'get', class: 'Jedis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['java'] },
541
+ { method: 'hget', class: 'Jedis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['java'] },
542
+ { method: 'mget', class: 'Jedis', type: 'db_input', severity: 'medium', return_tainted: true, languages: ['java'] },
543
+ // --- JWT claims (unverified decode — PyJWT / jose / jsonwebtoken / auth0 java-jwt / golang-jwt) ---
544
+ // A JWT's payload is *always* attacker-authored. Even after verification
545
+ // the *contents* of the claims (username, role, custom fields) are not
546
+ // trusted for downstream flows into SQL, HTML, shell, etc. The `decode`
547
+ // variants here return the parsed claims dictionary/object.
548
+ { method: 'decode', class: 'jwt', type: 'http_header', severity: 'high', return_tainted: true, languages: ['python'] },
549
+ { method: 'get_unverified_claims', class: 'jwt', type: 'http_header', severity: 'high', return_tainted: true, languages: ['python'] },
550
+ { method: 'get_unverified_header', class: 'jwt', type: 'http_header', severity: 'high', return_tainted: true, languages: ['python'] },
551
+ { method: 'decode', class: 'jwt', type: 'http_header', severity: 'high', return_tainted: true, languages: ['javascript', 'typescript'] },
552
+ { method: 'decode', class: 'jsonwebtoken', type: 'http_header', severity: 'high', return_tainted: true, languages: ['javascript', 'typescript'] },
553
+ { method: 'decodeJwt', class: 'jose', type: 'http_header', severity: 'high', return_tainted: true, languages: ['javascript', 'typescript'] },
554
+ { method: 'decodeProtectedHeader', class: 'jose', type: 'http_header', severity: 'high', return_tainted: true, languages: ['javascript', 'typescript'] },
555
+ { method: 'decode', class: 'JWT', type: 'http_header', severity: 'high', return_tainted: true, languages: ['java'] },
556
+ { method: 'ParseUnverified', class: 'jwt', type: 'http_header', severity: 'high', return_tainted: true, languages: ['go'] },
478
557
  ];
479
558
  export const DEFAULT_SINKS = [
480
559
  // SQL Injection (CWE-89)
@@ -2041,6 +2120,84 @@ export const DEFAULT_SINKS = [
2041
2120
  // they iterate after net/http entries and don't hijack `http.Get`.
2042
2121
  { method: 'Do', class: 'Client', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['go'] }, // *fasthttp.Client.Do(req)
2043
2122
  { method: 'DoTimeout', class: 'Client', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0], languages: ['go'] },
2123
+ // =========================================================================
2124
+ // cognium-dev #248 — prompt-injection sinks (CWE-1427)
2125
+ //
2126
+ // Tainted data reaching a generative-model prompt-construction API is
2127
+ // classified as `prompt_injection`. v1 uses broad positional matching
2128
+ // (arg_positions [0..3]) because these APIs are kwarg-heavy: Python
2129
+ // `openai.chat.completions.create(model=..., messages=...)` may pass the
2130
+ // messages arg at position 0 or 1 depending on caller order, and JS/TS
2131
+ // object-literal `{ messages: [...], model: '...' }` is a single
2132
+ // positional arg whose taint is inherited from any tainted property.
2133
+ // Argname-precise matching (messages=/prompt=/content=) and
2134
+ // sanitizer credit for prompt-template libraries (PromptTemplate,
2135
+ // ChatPromptTemplate) are follow-ups.
2136
+ //
2137
+ // Class-qualified entries prevent bare `create()` / `generate()` calls
2138
+ // with no receiver from matching (per taint-matcher.ts:1696 guard).
2139
+ // =========================================================================
2140
+ // --- Python: openai (v1 SDK) --------------------------------------------
2141
+ { method: 'create', class: 'Completions', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2142
+ { method: 'create', class: 'Responses', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2143
+ // openai <1.0 legacy top-level API — `openai.ChatCompletion.create(...)` / `openai.Completion.create(...)`
2144
+ { method: 'create', class: 'ChatCompletion', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2145
+ { method: 'create', class: 'Completion', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2146
+ // --- Python: anthropic ---------------------------------------------------
2147
+ { method: 'create', class: 'Messages', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2148
+ { method: 'stream', class: 'Messages', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2149
+ // --- Python: litellm (bare functions from the litellm module) -----------
2150
+ { method: 'completion', class: 'litellm', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2151
+ { method: 'acompletion', class: 'litellm', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2152
+ // --- Python: langchain chat/llm models ----------------------------------
2153
+ // Common concrete classes; matching the class name catches typical usage
2154
+ // `ChatOpenAI().invoke(prompt)` where the receiver-type resolver identifies
2155
+ // the class from the constructor.
2156
+ { method: 'invoke', class: 'ChatOpenAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2157
+ { method: 'predict', class: 'ChatOpenAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2158
+ { method: 'stream', class: 'ChatOpenAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2159
+ { method: 'generate', class: 'ChatOpenAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2160
+ { method: 'invoke', class: 'ChatAnthropic', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2161
+ { method: 'invoke', class: 'ChatGoogleGenerativeAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2162
+ { method: 'run', class: 'LLMChain', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2163
+ { method: 'invoke', class: 'LLMChain', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['python'] },
2164
+ // --- JS/TS: openai node SDK ---------------------------------------------
2165
+ { method: 'create', class: 'Completions', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2166
+ { method: 'create', class: 'Responses', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2167
+ // --- JS/TS: @anthropic-ai/sdk -------------------------------------------
2168
+ { method: 'create', class: 'Messages', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2169
+ { method: 'stream', class: 'Messages', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2170
+ // --- JS/TS: Vercel AI SDK (bare functions from the `ai` package) --------
2171
+ // generateText/streamText/generateObject take a single options object;
2172
+ // taint reaches the sink when a tainted variable flows into any property.
2173
+ { method: 'generateText', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
2174
+ { method: 'streamText', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
2175
+ { method: 'generateObject', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
2176
+ { method: 'streamObject', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
2177
+ // --- JS/TS: langchain.js ------------------------------------------------
2178
+ { method: 'invoke', class: 'ChatOpenAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2179
+ { method: 'invoke', class: 'ChatAnthropic', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2180
+ { method: 'stream', class: 'ChatOpenAI', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
2181
+ // --- Java: LangChain4j --------------------------------------------------
2182
+ { method: 'generate', class: 'ChatLanguageModel', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2183
+ { method: 'chat', class: 'ChatLanguageModel', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2184
+ { method: 'generate', class: 'StreamingChatLanguageModel', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2185
+ { method: 'chat', class: 'StreamingChatLanguageModel', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2186
+ // --- Java: Spring AI ----------------------------------------------------
2187
+ { method: 'prompt', class: 'ChatClient', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2188
+ { method: 'call', class: 'ChatClient', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2189
+ { method: 'call', class: 'ChatModel', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2190
+ // --- Java: OpenAI Java SDK (theokanning) --------------------------------
2191
+ { method: 'createChatCompletion', class: 'OpenAiService', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2192
+ { method: 'createCompletion', class: 'OpenAiService', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['java'] },
2193
+ // --- Go: go-openai (sashabaranov/go-openai) -----------------------------
2194
+ { method: 'CreateChatCompletion', class: 'Client', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['go'] },
2195
+ { method: 'CreateCompletion', class: 'Client', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['go'] },
2196
+ { method: 'CreateChatCompletionStream', class: 'Client', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['go'] },
2197
+ // --- Go: langchaingo ----------------------------------------------------
2198
+ { method: 'Call', class: 'LLM', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['go'] },
2199
+ { method: 'Generate', class: 'LLM', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['go'] },
2200
+ { method: 'GenerateContent', class: 'Model', type: 'prompt_injection', cwe: 'CWE-1427', severity: 'high', arg_positions: [0, 1, 2, 3], languages: ['go'] },
2044
2201
  ];
2045
2202
  export const DEFAULT_SANITIZERS = [
2046
2203
  // SQL Injection - proper parameter binding sanitizes input