mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-28 07:32:14 +02:00
* 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
139 lines
5.9 KiB
C
139 lines
5.9 KiB
C
#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
|