Commit 5e664f4
docs: align README examples with current Pydantic API (#336)
## Summary
- **`controls.isHardened`**: `web.isHardened = True` and `db.isHardened
= False` changed to `web.controls.isHardened = True` /
`db.controls.isHardened = False`. `isHardened` lives on `Controls`, not
on `Element`. Because `Element` has `extra="allow"`, the old form
**failed silently** — it stored the value as an extra field and left
`controls.isHardened` at its default.
- **`controls.hasAccessControl`**: `my_lambda.hasAccessControl = True` →
`my_lambda.controls.hasAccessControl = True`. Same silent-failure
mechanism.
- **`db.type = DatastoreType.SQL`**: `db.isSql = True` → `db.type =
DatastoreType.SQL`. The actual field is `isSQL` (uppercase), not
`isSql`; `isSql` was silently stored as an extra field. The shipped
`tm.py` uses `DatastoreType.SQL`.
- **`sourceFiles`**: `web.sourceCode` and `db.sourceCode` →
`web.sourceFiles = [...]` / `db.sourceFiles = [...]`. `sourceFiles` is a
`List[str]` on `Element`; `sourceCode` was silently ignored.
- **`DatastoreType` import**: Added to the sample import list (required
by `db.type = DatastoreType.SQL`).
- **`--describe` block**: Replaced stale hand-written output (showing
pre-Pydantic fields that no longer exist) with verbatim output of
`./tm.py --describe Server`, which shows the full inherited attribute
set including `controls`, `sourceFiles`, `minTLSVersion`, etc.
- **Usage block**: Updated synopsis (added `--colormap` to synopsis
line; changed `optional arguments:` to `options:` — Python 3.10+
argparse wording).
- **Threat condition example**: `f.sink.isSQL` → `f.sink.type ==
DatastoreType.SQL`. `isSQL` is a valid bool field (still exists,
defaults `True`) but is non-discriminating for all Datastores by
default; `type == DatastoreType.SQL` matches the idiom in the shipped
`tm.py`.
## Verified failure mode of old sample
`extra="allow"` on Pydantic models means every stale attribute set
(`web.isHardened`, `db.isSql`, `web.sourceCode`, etc.) was silently
stored in `model_extra` rather than raising a `ValidationError`. No
error was raised; the intended fields were simply never set.
## Validation
```
# Corrected sample
python /tmp/sample.py --dfd > /dev/null # OK
python /tmp/sample.py --report docs/basic_template.md > /dev/null # OK
# Test suite
uv run pytest tests/ -x -q # 243 passed
# Diff touches only README.md
git diff --stat HEAD~1 # README.md | 93 +++...
```
## Hypotheses that turned out wrong
- The hypothesis stated the README uses `from pytm.pytm import`; it
already used `from pytm import` correctly. Only the missing
`DatastoreType` in the import list needed fixing.
- `docs/threats.md` hits from the `grep` sweep
(`target.controls.isHardened`, `target.controls.hasAccessControl`) are
already in correct form — no changes needed there.
## Out-of-scope finding
`./tm.py --describe Element` errors with "No such class to describe:
Element" because `Element` is not added to `_CLASS_REGISTRY` in
`pytm/pytm.py` (only its subclasses are added via `_iter_subclasses`).
Tracked separately.
---------
Co-authored-by: snyk-bot <snyk-bot@snyk.io>1 parent bc4e7be commit 5e664f4
1 file changed
Lines changed: 68 additions & 26 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
79 | | - | |
| 78 | + | |
| 79 | + | |
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| |||
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
127 | 168 | | |
128 | 169 | | |
129 | 170 | | |
| |||
146 | 187 | | |
147 | 188 | | |
148 | 189 | | |
149 | | - | |
| 190 | + | |
| 191 | + | |
150 | 192 | | |
151 | 193 | | |
152 | 194 | | |
| |||
160 | 202 | | |
161 | 203 | | |
162 | 204 | | |
163 | | - | |
164 | | - | |
| 205 | + | |
| 206 | + | |
165 | 207 | | |
166 | 208 | | |
167 | 209 | | |
168 | | - | |
| 210 | + | |
169 | 211 | | |
170 | | - | |
| 212 | + | |
171 | 213 | | |
172 | | - | |
| 214 | + | |
173 | 215 | | |
174 | 216 | | |
175 | 217 | | |
| |||
196 | 238 | | |
197 | 239 | | |
198 | 240 | | |
199 | | - | |
| 241 | + | |
200 | 242 | | |
201 | 243 | | |
202 | 244 | | |
| |||
393 | 435 | | |
394 | 436 | | |
395 | 437 | | |
396 | | - | |
| 438 | + | |
397 | 439 | | |
398 | 440 | | |
399 | 441 | | |
| |||
0 commit comments