Skip to content

bug: Dead elsif branch in __sysopen permission check silently bypasses parent-dir write-permission enforcement #329

@Koan-Bot

Description

@Koan-Bot

Problem

In __sysopen, line 3349 returns ENOENT whenever $mock_file->{'contents'} is undef. This means that by the time execution reaches the permission block at line 3357, $mock_file->{'contents'} is always defined — the elsif ($rw =~ /w/) branch at line 3367 (which checks parent-directory write+execute permission before creating a new file) is unreachable dead code. The equivalent path in __open (line 2827) does reach its elsif and correctly enforces the parent-dir check.

Why This Matters

With set_user() active, sysopen($fh, '/protected/new', O_WRONLY|O_CREAT) will create a file in a restricted directory without error, while open($fh, '>', '/protected/new') correctly returns EACCES. This is a permissions-enforcement inconsistency that could cause tests to pass incorrectly.

Suggested Fix

Move the parent-dir permission check to before the O_CREAT initialization block (lines 3312-3313), or restructure with a flag: save my $is_new = !defined $mock_file->{'contents'} before O_CREAT sets contents to '', then test $is_new in the elsif at line 3367. Example:

my $is_new = !defined $mock_file->{'contents'};
# ... O_CREAT / O_TRUNC logic ...
if ( defined $_mock_uid ) {
    if ( !$is_new ) {
        # existing file — check file perms
    } elsif ( $rw =~ /w/ ) {
        # new file — check parent dir perms
    }
}

Details

Severity 🟠 High
Category robustness
Location lib/Test/MockFile.pm:3349-3374
Effort ⚡ Quick fix

🤖 Created by Kōan from audit session

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions