@@ -119,7 +119,7 @@ func TestWakeTargetRejectsWorldWritableInjectVia(t *testing.T) {
119119 if err := os .Chmod (injector , 0o777 ); err != nil {
120120 t .Fatalf ("chmod injector: %v" , err )
121121 }
122- err := validateWakeInjectViaPath (injector )
122+ _ , err := validateWakeInjectViaPath (injector )
123123 if err == nil || ! strings .Contains (err .Error (), "group/world-writable" ) {
124124 t .Fatalf ("expected world-writable rejection, got %v" , err )
125125 }
@@ -143,22 +143,26 @@ func TestWakeTargetRejectsWorldWritableInjectViaAncestor(t *testing.T) {
143143 t .Fatalf ("write injector: %v" , err )
144144 }
145145
146- err := validateWakeInjectViaPath (injector )
146+ _ , err := validateWakeInjectViaPath (injector )
147147 if err == nil || ! strings .Contains (err .Error (), "group/world-writable" ) {
148148 t .Fatalf ("expected writable ancestor rejection, got %v" , err )
149149 }
150150}
151151
152- func TestWakeTargetRejectsSymlinkInjectVia (t * testing.T ) {
152+ func TestWakeTargetResolvesLeafSymlinkInjectVia (t * testing.T ) {
153+ root := secureTempDirForTest (t )
153154 injector := writeExecutableForTest (t , "injector" )
154155 link := filepath .Join (t .TempDir (), "injector-link" )
155156 if err := os .Symlink (injector , link ); err != nil {
156157 t .Fatalf ("symlink injector: %v" , err )
157158 }
158159
159- err := validateWakeInjectViaPath (link )
160- if err == nil || ! strings .Contains (err .Error (), "must not be a symlink" ) {
161- t .Fatalf ("expected symlink rejection, got %v" , err )
160+ target := mustNewWakeTargetForTest (t , root , "codex" , link , nil )
161+ if target .InjectVia != injector {
162+ t .Fatalf ("target inject_via = %q, want resolved %q" , target .InjectVia , injector )
163+ }
164+ if err := validateWakeTarget (target , root , "codex" ); err != nil {
165+ t .Fatalf ("validateWakeTarget: %v" , err )
162166 }
163167}
164168
@@ -207,7 +211,7 @@ func TestWakeTargetResolvesSymlinkedInjectViaParent(t *testing.T) {
207211 }
208212}
209213
210- func TestWakeTargetKeepsSymlinkInjectViaForValidationRejection (t * testing.T ) {
214+ func TestWakeTargetResolvesLeafSymlinkInjectViaForValidation (t * testing.T ) {
211215 base := secureTempDirForTest (t )
212216 injector := writeExecutableForTest (t , "injector" )
213217 link := filepath .Join (base , "injector-link" )
@@ -216,11 +220,64 @@ func TestWakeTargetKeepsSymlinkInjectViaForValidationRejection(t *testing.T) {
216220 }
217221
218222 target := mustNewWakeTargetForTest (t , base , "codex" , link , nil )
219- if target .InjectVia != link {
220- t .Fatalf ("target inject_via = %q, want unresolved symlink %q" , target .InjectVia , link )
223+ if target .InjectVia != injector {
224+ t .Fatalf ("target inject_via = %q, want resolved %q" , target .InjectVia , injector )
225+ }
226+ if err := validateWakeTarget (target , base , "codex" ); err != nil {
227+ t .Fatalf ("validateWakeTarget: %v" , err )
228+ }
229+ }
230+
231+ func TestWakeTargetRejectsDanglingSymlinkInjectVia (t * testing.T ) {
232+ root := secureTempDirForTest (t )
233+ link := filepath .Join (root , "injector-link" )
234+ if err := os .Symlink (filepath .Join (root , "missing-injector" ), link ); err != nil {
235+ t .Fatalf ("symlink injector: %v" , err )
236+ }
237+
238+ _ , err := newWakeTarget (root , "codex" , link , nil )
239+ if err == nil || ! strings .Contains (err .Error (), "resolve inject_via" ) {
240+ t .Fatalf ("expected dangling symlink rejection, got %v" , err )
241+ }
242+ }
243+
244+ func TestWakeTargetRejectsSymlinkToNonExecutableInjectVia (t * testing.T ) {
245+ root := secureTempDirForTest (t )
246+ injector := filepath .Join (root , "injector" )
247+ if err := os .WriteFile (injector , []byte ("#!/bin/sh\n exit 0\n " ), 0o644 ); err != nil {
248+ t .Fatalf ("write injector: %v" , err )
221249 }
222- if err := validateWakeTarget (target , base , "codex" ); err == nil || ! strings .Contains (err .Error (), "must not be a symlink" ) {
223- t .Fatalf ("expected symlink validation rejection, got %v" , err )
250+ link := filepath .Join (root , "injector-link" )
251+ if err := os .Symlink (injector , link ); err != nil {
252+ t .Fatalf ("symlink injector: %v" , err )
253+ }
254+
255+ _ , err := newWakeTarget (root , "codex" , link , nil )
256+ if err == nil || ! strings .Contains (err .Error (), "not executable" ) {
257+ t .Fatalf ("expected non-executable resolved target rejection, got %v" , err )
258+ }
259+ }
260+
261+ func TestWakeTargetRejectsSymlinkToNonOwnedInjectVia (t * testing.T ) {
262+ oldCurrent := wakeTargetCurrentUID
263+ oldOwner := wakeTargetFileOwnerUID
264+ wakeTargetCurrentUID = func () (int , bool ) { return 1000 , true }
265+ wakeTargetFileOwnerUID = func (info os.FileInfo ) (int , bool ) { return 2000 , true }
266+ t .Cleanup (func () {
267+ wakeTargetCurrentUID = oldCurrent
268+ wakeTargetFileOwnerUID = oldOwner
269+ })
270+
271+ root := secureTempDirForTest (t )
272+ injector := writeExecutableForTest (t , "injector" )
273+ link := filepath .Join (root , "injector-link" )
274+ if err := os .Symlink (injector , link ); err != nil {
275+ t .Fatalf ("symlink injector: %v" , err )
276+ }
277+
278+ _ , err := newWakeTarget (root , "codex" , link , nil )
279+ if err == nil || ! strings .Contains (err .Error (), "owned by uid 2000" ) {
280+ t .Fatalf ("expected owner rejection, got %v" , err )
224281 }
225282}
226283
@@ -229,8 +286,8 @@ func TestWakeTargetCreationRejectsMissingInjectVia(t *testing.T) {
229286 missing := filepath .Join (root , "missing-injector" )
230287
231288 _ , err := newWakeTarget (root , "codex" , missing , nil )
232- if err == nil || ! strings .Contains (err .Error (), "stat inject_via" ) {
233- t .Fatalf ("expected inject_via stat failure, got %v" , err )
289+ if err == nil || ! strings .Contains (err .Error (), "resolve inject_via" ) {
290+ t .Fatalf ("expected inject_via resolve failure, got %v" , err )
234291 }
235292}
236293
@@ -239,7 +296,7 @@ func TestWakeTargetRejectsGroupWritableInjectVia(t *testing.T) {
239296 if err := os .Chmod (injector , 0o775 ); err != nil {
240297 t .Fatalf ("chmod injector: %v" , err )
241298 }
242- err := validateWakeInjectViaPath (injector )
299+ _ , err := validateWakeInjectViaPath (injector )
243300 if err == nil || ! strings .Contains (err .Error (), "group/world-writable" ) {
244301 t .Fatalf ("expected group-writable rejection, got %v" , err )
245302 }
@@ -248,7 +305,7 @@ func TestWakeTargetRejectsGroupWritableInjectVia(t *testing.T) {
248305func TestWakeTargetRejectsNonRegularInjectVia (t * testing.T ) {
249306 path := t .TempDir ()
250307
251- err := validateWakeInjectViaPath (path )
308+ _ , err := validateWakeInjectViaPath (path )
252309 if err == nil || ! strings .Contains (err .Error (), "must be a regular file" ) {
253310 t .Fatalf ("expected non-regular rejection, got %v" , err )
254311 }
@@ -265,7 +322,7 @@ func TestWakeTargetRejectsNonOwnedInjectVia(t *testing.T) {
265322 })
266323
267324 injector := writeExecutableForTest (t , "injector" )
268- err := validateWakeInjectViaPath (injector )
325+ _ , err := validateWakeInjectViaPath (injector )
269326 if err == nil || ! strings .Contains (err .Error (), "owned by uid 2000" ) {
270327 t .Fatalf ("expected owner rejection, got %v" , err )
271328 }
0 commit comments