@portll/cobolwork 0.5.0 → 0.6.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 (69) hide show
  1. package/README.md +43 -11
  2. package/bin/cobolwork.mjs +27 -8
  3. package/lib/baseline.mjs +9 -0
  4. package/lib/build.mjs +33 -8
  5. package/lib/capabilities.mjs +4 -1
  6. package/lib/consequence.mjs +4 -0
  7. package/lib/control-reuse.mjs +113 -0
  8. package/lib/control.mjs +25 -1
  9. package/lib/dataflow.mjs +285 -86
  10. package/lib/equivalence.mjs +44 -5
  11. package/lib/evidence/cli.mjs +13 -5
  12. package/lib/evidence/record.mjs +16 -6
  13. package/lib/evidence/seal.mjs +17 -0
  14. package/lib/evidence/store.mjs +30 -14
  15. package/lib/evidence/timestamp.mjs +83 -0
  16. package/lib/evidence/verify.mjs +120 -42
  17. package/lib/hlasm/asm/data.mjs +116 -0
  18. package/lib/hlasm/asm/listing.mjs +43 -0
  19. package/lib/hlasm/asm/output.mjs +45 -0
  20. package/lib/hlasm/asm/sections.mjs +159 -0
  21. package/lib/hlasm/asm/symbols.mjs +78 -0
  22. package/lib/hlasm/exec.mjs +27 -0
  23. package/lib/hlasm/expr.mjs +167 -0
  24. package/lib/hlasm/instr.mjs +48 -0
  25. package/lib/hlasm/locate.mjs +333 -0
  26. package/lib/hlasm/macro/authorization.mjs +126 -0
  27. package/lib/hlasm/macro/datasets.mjs +94 -0
  28. package/lib/hlasm/macro/io.mjs +139 -0
  29. package/lib/hlasm/macro/le.mjs +53 -0
  30. package/lib/hlasm/macro/linkage.mjs +143 -0
  31. package/lib/hlasm/macro/operator.mjs +66 -0
  32. package/lib/hlasm/macro/program.mjs +142 -0
  33. package/lib/hlasm/macro/recovery.mjs +80 -0
  34. package/lib/hlasm/macro/storage.mjs +117 -0
  35. package/lib/hlasm/macro/structured.mjs +131 -0
  36. package/lib/hlasm/model.mjs +72 -0
  37. package/lib/hlasm/operands.mjs +49 -0
  38. package/lib/hlasm/read.mjs +116 -0
  39. package/lib/inventory.mjs +10 -7
  40. package/lib/ironwork-ids.mjs +24 -0
  41. package/lib/ironwork.mjs +4 -1
  42. package/lib/kernel/registry.mjs +20 -17
  43. package/lib/kernel/shared-pass.mjs +138 -0
  44. package/lib/options.mjs +26 -4
  45. package/lib/policy.mjs +6 -0
  46. package/lib/precompile-cics.mjs +1 -1
  47. package/lib/revision.json +1 -1
  48. package/lib/sarif.mjs +3 -0
  49. package/lib/scan.mjs +21 -11
  50. package/lib/sets/abend.mjs +71 -7
  51. package/lib/sets/build.mjs +43 -37
  52. package/lib/sets/cics.mjs +5 -3
  53. package/lib/sets/compile.mjs +5 -3
  54. package/lib/sets/copybook.mjs +5 -3
  55. package/lib/sets/flow.mjs +14 -7
  56. package/lib/sets/hlasm.mjs +60 -4
  57. package/lib/sets/log.mjs +5 -3
  58. package/lib/sets/priv.mjs +5 -3
  59. package/lib/sets/secrets.mjs +110 -0
  60. package/lib/sets/semantics.mjs +5 -3
  61. package/lib/sets/web.mjs +5 -3
  62. package/package.json +1 -1
  63. package/rules/compliance-cobit2019.json +88 -4
  64. package/rules/compliance-dora.json +95 -4
  65. package/rules/compliance-ffiec.json +91 -0
  66. package/rules/compliance-nist80053.json +91 -0
  67. package/rules/gitleaks-mainframe.toml +46 -15
  68. package/rules/hlasm-instructions.json +2396 -0
  69. package/schema/cobolwork.policy.schema.json +7 -0
@@ -6,51 +6,72 @@ title = "commitwork mainframe credential rules"
6
6
  [extend]
7
7
  useDefault = false
8
8
 
9
+ # A rule with two capture groups and no secretGroup reports whichever group matched: a password
10
+ # written plain, or one in apostrophes, which a password phrase or a special character needs. A value
11
+ # in apostrophes that reaches column 71 continues on the next statement, so its first part is reported.
9
12
  [[rules]]
10
13
  id = "jcl-racf-password"
11
- description = "RACF password in a JCL statement (JOB card, EXEC PARM or DD)"
12
- regex = '''(?im)^//[^*\n][^\n]*?\bPASSWORD=\(?([A-Z0-9@#$]{1,8})(?:[,)'\s]|$)'''
13
- secretGroup = 1
14
+ description = "RACF password or password phrase in a JCL statement (JOB card, EXEC PARM or DD)"
15
+ regex = '''(?im)^//[^*\n][^\n]*?\bPASSWORD=\(?(?:([A-Z0-9@#$]{1,8})(?:[,)'\s]|$)|'((?:[^'\n]|'')+)(?:'|$))'''
14
16
  keywords = ["password="]
15
17
  [rules.allowlist]
16
- regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?)$''']
18
+ regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?|&[A-Z0-9@#$]{1,8}\.?|(?:your[-_ ]?)?pass(?:word)?[-_ ]?phrase)$''']
17
19
 
18
20
  [[rules]]
19
21
  id = "jcl-racf-new-password"
20
- description = "New RACF password in a JCL PASSWORD=(old,new)"
21
- regex = '''(?im)^//[^*\n][^\n]*?\bPASSWORD=\([A-Z0-9@#$]{1,8},([A-Z0-9@#$]{1,8})\)'''
22
- secretGroup = 1
22
+ description = "New RACF password or password phrase in a JCL PASSWORD=(old,new)"
23
+ regex = '''(?im)^//[^*\n][^\n]*?\bPASSWORD=\((?:[A-Z0-9@#$]{1,8}|'(?:[^'\n]|'')*'),(?:([A-Z0-9@#$]{1,8})\)|'((?:[^'\n]|'')+)(?:'\)|$))'''
23
24
  keywords = ["password="]
24
25
  [rules.allowlist]
25
- regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?)$''']
26
+ regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?|&[A-Z0-9@#$]{1,8}\.?|(?:your[-_ ]?)?pass(?:word)?[-_ ]?phrase)$''']
26
27
 
27
28
  [[rules]]
28
29
  id = "tso-logon-password"
29
30
  description = "TSO LOGON with an inline password"
30
- regex = '''(?im)^\s*LOGON\s+[A-Z@#$][A-Z0-9@#$]{0,7}/([A-Z0-9@#$]{1,8})\b'''
31
+ regex = '''(?im)^\s*LOGON\s+[A-Z@#$][A-Z0-9@#$]{0,7}[ \t,]*/[ \t,]*([A-Z0-9@#$]{1,8})\b'''
31
32
  secretGroup = 1
32
33
  keywords = ["logon"]
33
34
  [rules.allowlist]
34
35
  regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?)$''']
35
36
 
36
37
  [[rules]]
37
- id = "racf-command-password"
38
- description = "RACF ADDUSER or ALTUSER with an inline PASSWORD(...)"
39
- regex = '''(?i)\b(?:ALTUSER|ALU|ADDUSER|AU)\s+\(?[A-Z0-9@#$]{1,8}\)?[^\n]*?\bPASSWORD\(\s*([A-Z0-9@#$]{1,8})\s*\)'''
38
+ id = "tso-logon-new-password"
39
+ description = "New password in a TSO LOGON userid/password/new-password"
40
+ regex = '''(?im)^\s*LOGON\s+[A-Z@#$][A-Z0-9@#$]{0,7}[ \t,]*/[ \t,]*[A-Z0-9@#$]{1,8}[ \t,]*/[ \t,]*([A-Z0-9@#$]{1,8})\b'''
40
41
  secretGroup = 1
41
- keywords = ["password("]
42
+ keywords = ["logon"]
42
43
  [rules.allowlist]
43
44
  regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?)$''']
44
45
 
46
+ [[rules]]
47
+ id = "racf-command-password"
48
+ description = "RACF ADDUSER, ALTUSER, PASSWORD or PHRASE command with an inline password or password phrase"
49
+ regex = '''(?im)(?:\b(?:ALTUSER|ALU|ADDUSER|AU)\s+\(?[A-Z0-9@#$]{1,8}\)?[^\n]*?|^\s*(?:PASSWORD|PW|PHRASE)\s+(?:[^\n]*?\s)?)\b(?:PASSWORD\(\s*([A-Z0-9@#$]{1,8})(?:\s*\)|\s+[A-Z0-9@#$]{1,8}\s*\))|PHRASE\(\s*'((?:[^'\n]|'')+)'(?:\s*\)|\s+'(?:[^'\n]|'')*'\s*\)))'''
50
+ keywords = ["password(", "phrase("]
51
+ [rules.allowlist]
52
+ regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?|(?:your[-_ ]?)?pass(?:word)?[-_ ]?phrase)$''']
53
+
54
+ [[rules]]
55
+ id = "racf-command-new-password"
56
+ description = "New password or password phrase in a RACF PASSWORD or PHRASE command"
57
+ regex = '''(?im)^\s*(?:PASSWORD|PW|PHRASE)\s+(?:[^\n]*?\s)?\b(?:PASSWORD\(\s*[A-Z0-9@#$]{1,8}\s+([A-Z0-9@#$]{1,8})\s*\)|PHRASE\(\s*'(?:[^'\n]|'')*'\s+'((?:[^'\n]|'')+)'\s*\))'''
58
+ keywords = ["password(", "phrase("]
59
+ [rules.allowlist]
60
+ regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?|(?:your[-_ ]?)?pass(?:word)?[-_ ]?phrase)$''']
61
+
62
+ # Column 7 holds the indicator: '*' and '/' make the line a comment, and 'D' a debugging line, which
63
+ # is still source. A literal that runs to the end of its line is continued on the next, so the first
64
+ # part is enough to report it. A hexadecimal value under four bytes is a flag, and one byte repeated
65
+ # is a fill.
45
66
  [[rules]]
46
67
  id = "cobol-value-credential"
47
68
  description = "COBOL data item named for a credential with a literal VALUE"
48
- regex = '''(?im)^[^*\n]{0,7}\s*\b(?:0?[1-9]|[1-4][0-9]|77)\s+[A-Z0-9-]*(?:PASSWORD|PASSWD|PASSWRD|PSWD|PWD|SECRET|APIKEY|API-KEY|ACCESS-KEY|(?:API|ACCESS|AUTH|BEARER|OAUTH|REFRESH)-?TOKEN)[A-Z0-9-]*\b[^.]*?\bVALUES?\s+(?:IS\s+|ARE\s+)?(?:'([^'\n]{1,})'|"([^"\n]{1,})")'''
69
+ regex = '''(?im)^(?:(?:[^*\n]{0,6}|[^*\n]{6}[^*/\n])\s*\b|[^*\n]{6}[Dd])(?:0?[1-9]|[1-4][0-9]|77)\s+[A-Z0-9-]*(?:PASSWORD|PASSWD|PASSWRD|PSWD|PWD|SECRET|APIKEY|API-KEY|ACCESS-KEY|(?:API|ACCESS|AUTH|BEARER|OAUTH|REFRESH)-?TOKEN)[A-Z0-9-]*\b[^.]*?\bVALUES?\s+(?:IS\s+|ARE\s+)?(?:NX|UX|[XNGZU])?(?:'([^'\n]{1,})(?:'|$)|"([^"\n]{1,})(?:"|$))'''
49
70
  keywords = ["password", "passwd", "passwrd", "pswd", "pwd", "secret", "apikey", "api-key", "access-key", "token"]
50
71
  path = '''(?i)\.(?:cbl|cob|cobol|cpy|copy|sqb|pco|ccp)$'''
51
72
  [rules.allowlist]
52
73
  regexTarget = "match"
53
- regexes = ['''(?i)VALUE\s+(?:IS\s+)?['"](?:x+|\*+|\s+|y|n|yes|no|true|false|on|off|[01]|pass(?:word)?|secret|dummy|changeme|password:?|enter[^'"]*|invalid[^'"]*|wrong[^'"]*|[^'"]*\S\s+\S[^'"]*)['"]''']
74
+ regexes = ['''(?i)VALUES?\s+(?:IS\s+|ARE\s+)?(?:NX|UX|[XNGZU])?['"](?:x+|\*+|\s+|y|n|yes|no|true|false|on|off|[01]|pass(?:word)?|secret|dummy|changeme|password:?|enter[^'"]*|invalid[^'"]*|wrong[^'"]*|[^'"]*\S\s+\S[^'"]*)(?:['"]|$)''', '''(?i)VALUES?\s+(?:IS\s+|ARE\s+)?(?:NX|UX|X)['"](?:[0-9A-F]{1,7}|0+|(?:40)+|(?:20)+|F+|(?:F0)+)['"]''']
54
75
 
55
76
  [[rules]]
56
77
  id = "embedded-sql-connect-password"
@@ -69,3 +90,13 @@ secretGroup = 1
69
90
  keywords = ["password("]
70
91
  [rules.allowlist]
71
92
  regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?)$''']
93
+
94
+ # PHRASE and NEWPHRASE take a data area, which cannot be a literal, so only NEWPASSWORD can hold one.
95
+ [[rules]]
96
+ id = "cics-new-password"
97
+ description = "EXEC CICS SIGNON or CHANGE PASSWORD with a literal NEWPASSWORD"
98
+ regex = '''(?i)EXEC\s+CICS\s+(?:SIGNON|CHANGE)\b[^.]{0,300}?\bNEWPASSWORD\(\s*'([^'\n]{1,8})'\s*\)'''
99
+ secretGroup = 1
100
+ keywords = ["newpassword("]
101
+ [rules.allowlist]
102
+ regexes = ['''(?i)^(?:x+|\*+|y+|n+|pass|passw(?:or)?d?|pwd|secret|dummy|changeme|password|newpass(?:word)?|oldpass(?:word)?)$''']