v1.90.0.0 feat: make browser cookie imports explicit and safe (#2964)

* fix(browse): prepare reliable cookie import wave for validation

* ci: sequence quality and behavior for validation branch

* fix(browse): isolate Windows qualification and preserve native diagnostics

* test(browse): cover cookie workflow quality and isolate Windows user paths

* test(browse): trace native member startup and initialize fresh folders

* fix(browse): keep Windows member stdin alive through EOF

* fix(browse): latch native timeouts and compare contained Edge startup

* test(browse): verify native version metadata and actual Windows argv

* test(browse): qualify Dia import on isolated macOS CI

* fix(browse): require picker origin for session mutations

* fix(browse): bound credential reads through stream completion

* test(browse): inspect owned Windows process arguments natively

* test(evals): preserve passing coverage during cookie repair reruns

* test(browse): isolate Dia qualification in a fresh macOS account

* test(browse): pass bounded integer timeouts to native Mac probes

* test(browse): distinguish Windows profile initialization from containment

* test(browse): await descendant pipe readiness before parent exit

* test(browse): initialize and restore isolated macOS Keychain state

* test(browse): initialize Windows fixture folders before qualification

* test(ci): pin the same Node runtime across Windows checks

* test(browse): distinguish native macOS browser preflight stages

* test(browse): isolate Windows descendant console lifetime

* test(browse): preserve native receipts and identify fixture lock holders

* test(browse): prepare dependency resolution before native Mac worker startup

* test(ci): include lock and close checks in native diagnostics

* test(browse): preserve native owner probe stages and subprocess deadlines

* fix(browse): classify Chromium profile-in-use exit precisely

* test(browse): retain Mac qualification evidence through cleanup failures

* test(browse): bound Mac fixture paths and retire its owned user domain

* test(browse): accept vanished fixture entries without weakening cleanup

* test(browse): identify probe-created macOS user domains safely

* test(browse): observe Mac user domains without targeting them first

* test(browse): use passive fresh-user ownership throughout Mac qualification

* test(browse): distinguish profile and registered-home Keychain lookups

* test(browse): qualify Dia under one registered account home

* test(browse): identify Dia startup and owned process-group failures

* test(browse): classify bounded Dia startup diagnostics without leaking output

* fix(test): preserve native Mac sandboxing and reap owned browser children

* fix(browse): preserve Chromium sandboxing for native profile imports

* test(browse): inspect signed Mach-O architecture without launching Xcode tools

* test(browse): sample pending Dia startup and reap on all cleanup paths

* test(browse): compare protected Dia launches in fresh Bun and Node accounts

* test(browse): inspect isolated Mac GUI readiness without browser access

* v1.90.0.0 fix: bind cookie picker actions to their document

* test: validate cookie guards and fit nested launch fixtures

* ci: configure the bundled Chromium sandbox helper

* fix(browse): classify Playwright authentication timeouts

* test: retain bounded Windows lifecycle diagnostics

* test(cso): reuse bounded NTFS precision candidates

* test(review): handle explicit preservation choices safely

* test(browse): remove owned fixture directories with explicit primitives

* test(review): distinguish descriptive reuse from edit commitments

* test: admit only the approved unscored cookie workflow refusal

* test: keep the Office Hours judge mock export-complete

* fix: keep dependency-free CI planners independent of the model SDK

* test: observe the exact holder after a native fixture unlink failure

* fix: start seeded PTY observations at owned readiness

* test: acquire identity-bound Windows deletion admission before profile resets

* test: preserve qualified Git index bits without authorizing mutations
This commit is contained in:
Garry Tan
2026-09-25 12:06:45 -04:00
committed by GitHub
parent 730a1017d1
commit a84b0b5b6d
111 changed files with 14996 additions and 1057 deletions
+138
View File
@@ -0,0 +1,138 @@
#define _DARWIN_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef __APPLE__
#include <ApplicationServices/ApplicationServices.h>
#include <Security/AuthSession.h>
#endif
struct root_fact {
const char *state;
const char *kind;
int owner_matches;
int ancestor_blocked;
};
static const char *kind_of(mode_t mode) {
if (S_ISDIR(mode)) return "directory";
if (S_ISREG(mode)) return "file";
if (S_ISLNK(mode)) return "symlink";
return "other";
}
static struct root_fact inspect_root(int home, const char *relative, uid_t owner) {
struct root_fact fact = {"unavailable", NULL, -1, 0};
char components[256];
if (strlen(relative) >= sizeof(components)) return fact;
memcpy(components, relative, strlen(relative) + 1);
int directory = dup(home);
if (directory < 0) return fact;
char *state = NULL;
char *component = strtok_r(components, "/", &state);
while (component) {
char *next = strtok_r(NULL, "/", &state);
struct stat before;
if (fstatat(directory, component, &before, AT_SYMLINK_NOFOLLOW) != 0) {
if (errno == ENOENT) fact.state = "absent";
break;
}
fact.kind = kind_of(before.st_mode);
fact.owner_matches = before.st_uid == owner;
if (!next) { fact.state = "present"; break; }
if (!S_ISDIR(before.st_mode) || before.st_uid != owner) { fact.ancestor_blocked = 1; break; }
int child = openat(directory, component, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_NONBLOCK);
struct stat after;
if (child < 0) { fact.ancestor_blocked = 1; break; }
if (fstat(child, &after) != 0 || after.st_dev != before.st_dev || after.st_ino != before.st_ino
|| !S_ISDIR(after.st_mode) || after.st_uid != owner) {
close(child);
fact.ancestor_blocked = 1;
break;
}
close(directory);
directory = child;
fact.kind = NULL;
fact.owner_matches = -1;
component = next;
}
close(directory);
return fact;
}
static const char *boolean_or_null(int value) {
return value < 0 ? "null" : value ? "true" : "false";
}
static void print_browser_roots(int home, uid_t owner) {
const char *names[] = {"chrome", "chromium", "arc", "dia", "comet", "brave", "edge", "safari", "cookies"};
const char *paths[] = {"Library/Application Support/Google/Chrome", "Library/Application Support/Chromium",
"Library/Application Support/Arc", "Library/Application Support/Dia", "Library/Application Support/Comet",
"Library/Application Support/BraveSoftware/Brave-Browser", "Library/Application Support/Microsoft Edge", "Library/Safari", "Library/Cookies"};
printf("{");
for (size_t index = 0; index < sizeof(names) / sizeof(names[0]); index++) {
struct root_fact fact = inspect_root(home, paths[index], owner);
printf("%s\"%s\":{\"state\":\"%s\",\"kind\":", index ? "," : "", names[index], fact.state);
if (fact.kind) printf("\"%s\"", fact.kind); else printf("null");
printf(",\"ownerMatches\":%s,\"ancestorBlocked\":%s}", boolean_or_null(fact.owner_matches), boolean_or_null(fact.ancestor_blocked));
}
printf("}");
}
#ifdef __APPLE__
static int dictionary_boolean(CFDictionaryRef dictionary, CFStringRef key) {
CFTypeRef value = CFDictionaryGetValue(dictionary, key);
return value && CFGetTypeID(value) == CFBooleanGetTypeID() ? CFBooleanGetValue(value) : -1;
}
int main(int argc, char **argv) {
int browser_roots = argc == 2 && strcmp(argv[1], "--browser-roots") == 0;
if (argc != 1 && !browser_roots) return 2;
uid_t uid = getuid();
struct passwd *account = getpwuid(uid);
char registered[PATH_MAX], environment[PATH_MAX];
const char *home = getenv("HOME");
int home_matches = account && home && realpath(account->pw_dir, registered) && realpath(home, environment)
&& strcmp(registered, account->pw_dir) == 0 && strcmp(registered, environment) == 0;
int home_fd = home_matches ? open(registered, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_NONBLOCK) : -1;
struct stat home_info;
home_matches = home_fd >= 0 && fstat(home_fd, &home_info) == 0 && S_ISDIR(home_info.st_mode) && home_info.st_uid == uid;
SessionAttributeBits attributes = 0;
OSStatus status = SessionGetInfo(callerSecuritySession, NULL, &attributes);
CFDictionaryRef quartz = CGSessionCopyCurrentDictionary();
int same_uid = -1, login_done = -1, on_console = -1;
if (quartz) {
CFTypeRef value = CFDictionaryGetValue(quartz, kCGSessionUserIDKey);
long long session_uid = -1;
if (value && CFGetTypeID(value) == CFNumberGetTypeID() && CFNumberGetValue(value, kCFNumberLongLongType, &session_uid)) same_uid = session_uid == uid;
if (same_uid == 1) {
login_done = dictionary_boolean(quartz, kCGSessionLoginDoneKey);
on_console = dictionary_boolean(quartz, kCGSessionOnConsoleKey);
}
}
printf("{\"protocol\":1,\"supported\":true,\"identity\":{\"effectiveUidMatches\":%s,\"homeMatchesRegistered\":%s},",
boolean_or_null(geteuid() == uid), boolean_or_null(home_matches));
printf("\"security\":{\"status\":%d,\"graphicAccess\":%s,\"rootSession\":%s,\"tty\":%s,\"remote\":%s},",
(int)status, boolean_or_null(status ? -1 : !!(attributes & sessionHasGraphicAccess)), boolean_or_null(status ? -1 : !!(attributes & sessionIsRoot)),
boolean_or_null(status ? -1 : !!(attributes & sessionHasTTY)), boolean_or_null(status ? -1 : !!(attributes & sessionIsRemote)));
printf("\"quartz\":{\"present\":%s,\"sameUid\":%s,\"loginDone\":%s,\"onConsole\":%s},\"browserRoots\":",
boolean_or_null(quartz != NULL), boolean_or_null(same_uid), boolean_or_null(login_done), boolean_or_null(on_console));
if (browser_roots && home_matches) print_browser_roots(home_fd, uid); else printf("null");
printf("}\n");
if (home_fd >= 0) close(home_fd);
if (quartz) CFRelease(quartz);
return 0;
}
#else
int main(void) {
printf("{\"protocol\":1,\"supported\":false}\n");
return 2;
}
#endif