Repository navigation
Commit e678421
authored
feat(security-questionnaire): add browser extension (#3064)
* feat(security-questionnaire): add browser extension
* fix(security-questionnaire-extension): address review findings
- Use a closed shadow root for the domain confirmation dialog so the host
page cannot reach its controls.
- Escape leading formula characters when building Sheets paste TSV, so
answers starting with "-" stay text instead of being evaluated.
- Restrict the wildcard trusted-origin match to HTTPS; explicit localhost
entries are unaffected.
- Stop generate-all from overwriting approved or manually edited answers.
- Hold the inline preview locally so concurrent generates cannot render a
result into another field's preview.
- Finalize queue item status when single generation fails, instead of
leaving the item stuck in "generating".
- Implement the Google Docs footer copy action, which had no handler, and
label/enable the button to match.
Adds coverage for the paste plan, batch candidate selection, docs footer,
clipboard text, and the origin policy.
* fix(security-questionnaire-extension): make Google OAuth optional in release, add docs
The release workflow required a Google OAuth client id and failed the build
when the manifest had none, so the extension could not ship without direct
Google Sheets API access. Treat it as optional: verify the manifest only
when the secret is set, and drop it from the required-secret check.
Adds the extension documentation page and links it from the docs nav.
* fix(security-questionnaire-extension): resolve remaining review findings
Detection and data correctness:
- Stop dropping questionnaire rows whose text looks like a column label.
Any cell under 48 characters containing "control", "requirement" or
"question" was discarded, which silently lost common questions such as
"Are security controls documented?".
- Ignore answer-style statements in the keyword fallback so filled-in
answers are not re-detected as new questions.
- Reject row/column 0 when parsing sheet targets; A1 notation is 1-based.
- Reject negative sheet ids when building formatting requests.
Concurrency and data loss:
- Apply batch results to the stored queue rather than a snapshot, and skip
items the user edited or approved while generation was in flight.
- Serialize storage read-merge-writes so concurrent updates are not lost.
- Keep the sheet mapping dialog populated when a save fails.
- Surface autosave failures instead of dropping them.
Robustness:
- Guard JSON parsing in the API client, GViz table parsing and gid decoding.
- Let one Sheets endpoint failure fall through to the next.
- Fall back to local detection when the background message fails.
- Add Vary headers to CORS responses, including rejected origins.
- Trim organization ids and reject empty question ids and whitespace-only
approvals.
- Tighten isItemResponse to validate the queue it claims to carry.
Cleanup: drop the unused ReviewPanel and the unhandled
comp:generate-visible-page message, dedupe getHost and surface validation.
* fix(api): keep HEAD in the CORS allowed methods
The replacement CORS middleware dropped HEAD, which app.enableCors allowed
by default, so cross-origin HEAD preflights would have started failing.
* fix(security-questionnaire-extension): publish via service account on the working API
Switches Chrome Web Store auth from a personal refresh token to a service
account JWT, which does not expire and is not tied to an individual account.
Verified against the live API: the token exchange succeeds and the service
account can read the store item. Every v2 endpoint returns 404 for this
publisher while v1.1 works with the same token, so the upload, status and
publish calls now use v1.1. That API is supported until 2026-10-15.
Adds a publish_target choice so a manual run can ship to trusted testers
before going public.
* fix(security-questionnaire-extension): isolate failed queue writes in batch generation
A rejected save left the serialized write chain permanently rejected, so
every answer generated afterwards was computed and then silently dropped.
Keep the chain alive, collect per-item write failures instead of throwing
from a pool worker (which abandoned the questions queued behind it), and
report them once the batch has persisted everything it could.
* fix(security-questionnaire-extension): repair the manifest version check
The check embedded a JS template literal inside a double-quoted shell
string, so bash tried to expand ${process.env.VERSION} and aborted the
step with 'bad substitution'. The release workflow has never run, so this
would have failed on the first publish. Use string concatenation instead.
* fix(security-questionnaire-extension): drop the unused activeTab permission
Every activeTab occurrence in the source is a local variable name; the
permission itself is never relied on, and the <all_urls> host permission
already covers the same access. The store rejects versions that request
permissions they do not need.
Also refuses to publish a package whose manifest still points at
localhost, which is what the build produces when the public URL env vars
are missing.
* fix(security-questionnaire-extension): keep failed questions retryable
When a queue write failed the question stayed marked `generating`, and
that status is excluded from batch candidates — so every later Generate
All skipped it and the answer could never be recovered. Reset the item to
pending after a failed write.
* fix(security-questionnaire-extension): restore prior status after a failed write
Resetting a failed question to pending discarded whatever state it had
before the batch, so a transient storage error downgraded a question that
already held a generated or flagged answer. Restore the status captured
before the batch marked it generating.1 parent 539fdba commit e678421
125 files changed
Lines changed: 11712 additions & 197 deletions
File tree
- .github/workflows
- apps
- api/src
- auth
- common/filters
- questionnaire
- dto
- utils
- trigger/questionnaire
- browser-extension/security-questionnaire-ext
- public/icon
- src
- entrypoints
- popup
- sidepanel
- lib
- background
- dom
- types
- packages/docs
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 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 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
| 88 | + | |
| 89 | + | |
88 | 90 | | |
89 | 91 | | |
90 | 92 | | |
| |||
0 commit comments