Skip to content

False positives raised by check-executables-have-shebangs in VS Code Dev Containers #528

Description

@lsorber

When developing within a container using VS Code's Dev Containers feature, the check-executables-have-shebangs raises false positives for staged files, see log below. When switching back to local development, the same check passes without issue.

Check that executables have shebangs.....................................Failed
- hook id: check-executables-have-shebangs
- exit code: 1

.devcontainer/devcontainer.json: marked executable but has no (or invalid) shebang!
  If it isn't supposed to be executable, try: `chmod -x .devcontainer/devcontainer.json`
  If it is supposed to be executable, double-check its shebang.
.cruft.json: marked executable but has no (or invalid) shebang!
  If it isn't supposed to be executable, try: `chmod -x .cruft.json`
  If it is supposed to be executable, double-check its shebang.
.vscode/settings.json: marked executable but has no (or invalid) shebang!
  If it isn't supposed to be executable, try: `chmod -x .vscode/settings.json`
  If it is supposed to be executable, double-check its shebang.
environment.run.yml: marked executable but has no (or invalid) shebang!
  If it isn't supposed to be executable, try: `chmod -x environment.run.yml`
  If it is supposed to be executable, double-check its shebang.

Activity

  1. asottile commented on Nov 11, 2020

    @asottile
    Member

    please show your config, this was changed recently and you may not be on the latest version

    otherwise this may be a duplicate of #512? I'm not sure

    I assume you're on windows?

  2. asottile commented on Nov 11, 2020

    @asottile
    Member

    but, if vs code spaces is adding +x to every file, that's a problem with code spaces and not this tool

  3. lsorber commented on Nov 11, 2020

    @lsorber
    Author

    I'm on macOS, and pre-commit 3.2.0 produced the logs above. I checked the executable flag on each file and none of them were executable according to ls.

  4. asottile commented on Nov 11, 2020

    @asottile
    Member

    what happens if you use os.access(file, os.X_OK) on the particular file? that's how pre-commit determines if the file is executable or not

  5. lsorber commented on Nov 12, 2020

    @lsorber
    Author

    With pre-commit 3.3.0:
    image

    And checking os.access:
    image

  6. asottile commented on Nov 12, 2020

    @asottile
    Member

    you still haven't shown your configuration, there's no such version 3.3.0 of pre-commit (and the pre-commit version isn't relevant here)

    do you know what operating system the remote "container" is running on? can you run this: https://github.com/asottile/scratch/wiki/platforms

  7. lsorber commented on Nov 12, 2020

    @lsorber
    Author

    I meant 3.3.0 of the pre-commit hooks.

    Here's my .pre-commit-config.yaml, nothing special:

    # https://pre-commit.com
    default_stages: [commit, manual]
    fail_fast: true
    repos:
      - repo: https://github.com/pre-commit/pre-commit-hooks
        rev: v3.3.0
        hooks:
          - id: check-added-large-files
          - id: check-ast
          - id: check-builtin-literals
          - id: check-byte-order-marker
          - id: check-case-conflict
          - id: check-docstring-first
          - id: check-executables-have-shebangs
          - id: check-json
          - id: check-merge-conflict
          - id: check-symlinks
          - id: check-toml
          - id: check-vcs-permalinks
          - id: check-xml
          - id: check-yaml
          - id: debug-statements
          - id: detect-private-key
          - id: mixed-line-ending
          - id: trailing-whitespace
            types: [python]
          - id: end-of-file-fixer
            types: [python]
    

    Here's the output of that script (from within the container, the host system is macOS):

    - **`sys.version`**: `'3.8.6 | packaged by conda-forge | (default, Oct  7 2020, 19:08:05) \n[GCC 7.5.0]'`
    - **`os.name`**: `'posix'`
    - **`sys.platform`**: `'linux'`
    - **`platform.system()`**: `'Linux'`
    - **`platform.python_implementation()`**: `'CPython'`
    - **`sys.implementation.name`**: `'cpython'`
    - **`sysconfig.get_platform()`**: `'linux-x86_64'`
    
  8. asottile commented on Nov 12, 2020

    @asottile
    Member

    can you docker inspect the container, it seems really strange that a non-executable file would be reported as executable to linux. I wonder if this is a bug in the filesystem drivers for docker4mac

  9. lsorber commented on Nov 14, 2020

    @lsorber
    Author

    Output of docker inspect:

    [
        {
            "Id": "9d9f01db0067d24c5de277d829d37fee7c06ce7de0eaa694a0845c003e7c9015",
            "Created": "2020-11-13T08:47:56.6275981Z",
            "Path": "/bin/sh",
            "Args": [
                "-c",
                "echo Container started ; trap \"exit 0\" 15; while sleep 1 \u0026 wait $!; do :; done"
            ],
            "State": {
                "Status": "running",
                "Running": true,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 94806,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2020-11-14T14:20:31.2729275Z",
                "FinishedAt": "2020-11-13T14:50:04.4044059Z"
            },
            "Image": "sha256:b4adc22212f1c4628a1922a5669640e86734d0da3c26a0c35cb034e388c033ae",
            "ResolvConfPath": "/var/lib/docker/containers/9d9f01db0067d24c5de277d829d37fee7c06ce7de0eaa694a0845c003e7c9015/resolv.conf",
            "HostnamePath": "/var/lib/docker/containers/9d9f01db0067d24c5de277d829d37fee7c06ce7de0eaa694a0845c003e7c9015/hostname",
            "HostsPath": "/var/lib/docker/containers/9d9f01db0067d24c5de277d829d37fee7c06ce7de0eaa694a0845c003e7c9015/hosts",
            "LogPath": "/var/lib/docker/containers/9d9f01db0067d24c5de277d829d37fee7c06ce7de0eaa694a0845c003e7c9015/9d9f01db0067d24c5de277d829d37fee7c06ce7de0eaa694a0845c003e7c9015-json.log",
            "Name": "/loving_kirch",
            "RestartCount": 0,
            "Driver": "overlay2",
            "Platform": "linux",
            "MountLabel": "",
            "ProcessLabel": "",
            "AppArmorProfile": "",
            "ExecIDs": [
                "3bfd52c6ed470099ceac7ddb75ccbf9283101b51dff565f17c1f04c9de99fc24",
                "afa0ce201c8e886395ba8a3e14e20f00ecf870335b273ce746df02bbd574fbad",
                "570ddb310a76f8ef91ce46165d354536ae79db7adb7a0fd85a3582a768fb2211",
                "72723362588a07fdbdd9ec62e0496fc92fac25b35200633ca391032a1e59af1d"
            ],
            "HostConfig": {
                "Binds": null,
                "ContainerIDFile": "",
                "LogConfig": {
                    "Type": "json-file",
                    "Config": {}
                },
                "NetworkMode": "default",
                "PortBindings": {},
                "RestartPolicy": {
                    "Name": "no",
                    "MaximumRetryCount": 0
                },
                "AutoRemove": false,
                "VolumeDriver": "",
                "VolumesFrom": null,
                "CapAdd": null,
                "CapDrop": null,
                "Capabilities": null,
                "Dns": [],
                "DnsOptions": [],
                "DnsSearch": [],
                "ExtraHosts": null,
                "GroupAdd": null,
                "IpcMode": "private",
                "Cgroup": "",
                "Links": null,
                "OomScoreAdj": 0,
                "PidMode": "",
                "Privileged": false,
                "PublishAllPorts": false,
                "ReadonlyRootfs": false,
                "SecurityOpt": null,
                "UTSMode": "",
                "UsernsMode": "",
                "ShmSize": 67108864,
                "Runtime": "runc",
                "ConsoleSize": [
                    0,
                    0
                ],
                "Isolation": "",
                "CpuShares": 0,
                "Memory": 0,
                "NanoCpus": 0,
                "CgroupParent": "",
                "BlkioWeight": 0,
                "BlkioWeightDevice": [],
                "BlkioDeviceReadBps": null,
                "BlkioDeviceWriteBps": null,
                "BlkioDeviceReadIOps": null,
                "BlkioDeviceWriteIOps": null,
                "CpuPeriod": 0,
                "CpuQuota": 0,
                "CpuRealtimePeriod": 0,
                "CpuRealtimeRuntime": 0,
                "CpusetCpus": "",
                "CpusetMems": "",
                "Devices": [],
                "DeviceCgroupRules": null,
                "DeviceRequests": null,
                "KernelMemory": 0,
                "KernelMemoryTCP": 0,
                "MemoryReservation": 0,
                "MemorySwap": 0,
                "MemorySwappiness": null,
                "OomKillDisable": false,
                "PidsLimit": null,
                "Ulimits": null,
                "CpuCount": 0,
                "CpuPercent": 0,
                "IOMaximumIOps": 0,
                "IOMaximumBandwidth": 0,
                "Mounts": [
                    {
                        "Type": "bind",
                        "Source": "/Users/laurent/repos/[masked]/packages/entities",
                        "Target": "/workspaces/entities",
                        "Consistency": "cached"
                    }
                ],
                "MaskedPaths": [
                    "/proc/asound",
                    "/proc/acpi",
                    "/proc/kcore",
                    "/proc/keys",
                    "/proc/latency_stats",
                    "/proc/timer_list",
                    "/proc/timer_stats",
                    "/proc/sched_debug",
                    "/proc/scsi",
                    "/sys/firmware"
                ],
                "ReadonlyPaths": [
                    "/proc/bus",
                    "/proc/fs",
                    "/proc/irq",
                    "/proc/sys",
                    "/proc/sysrq-trigger"
                ]
            },
            "GraphDriver": {
                "Data": {
                    "LowerDir": "/var/lib/docker/overlay2/6e373796ee78f45c33898a90e26c24cef2cf0853aec34d71c01b33c061fb1691-init/diff:/var/lib/docker/overlay2/32f294bd3de39f73b9786e712839b0f563c6c2216bfd5892f622a809874363b6/diff:/var/lib/docker/overlay2/c2e96963e5bd0aa1167c90a11dceded2b2522e69ac7439d228d6b686a4eaadfb/diff:/var/lib/docker/overlay2/db4d49dc5ce540119c569ded7e6defc9c8dc9ad22310a038c6e0c8355e453496/diff",
                    "MergedDir": "/var/lib/docker/overlay2/6e373796ee78f45c33898a90e26c24cef2cf0853aec34d71c01b33c061fb1691/merged",
                    "UpperDir": "/var/lib/docker/overlay2/6e373796ee78f45c33898a90e26c24cef2cf0853aec34d71c01b33c061fb1691/diff",
                    "WorkDir": "/var/lib/docker/overlay2/6e373796ee78f45c33898a90e26c24cef2cf0853aec34d71c01b33c061fb1691/work"
                },
                "Name": "overlay2"
            },
            "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/Users/laurent/repos/[masked]/packages/entities",
                    "Destination": "/workspaces/entities",
                    "Mode": "",
                    "RW": true,
                    "Propagation": "rprivate"
                }
            ],
            "Config": {
                "Hostname": "9d9f01db0067",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": true,
                "AttachStderr": true,
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "LANG=C.UTF-8",
                    "LC_ALL=C.UTF-8"
                ],
                "Cmd": [
                    "-c",
                    "echo Container started ; trap \"exit 0\" 15; while sleep 1 \u0026 wait $!; do :; done"
                ],
                "Image": "continuumio/miniconda3:latest",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": [
                    "/bin/sh"
                ],
                "OnBuild": null,
                "Labels": {
                    "vsch.local.folder": "/Users/laurent/repos/[masked]/packages/entities",
                    "vsch.quality": "stable",
                    "vsch.remote.devPort": "0"
                }
            },
            "NetworkSettings": {
                "Bridge": "",
                "SandboxID": "d2c3bcb24dadcf221700f76c5e32f9bacd625aa3ac3a131d741d2638addbb3f4",
                "HairpinMode": false,
                "LinkLocalIPv6Address": "",
                "LinkLocalIPv6PrefixLen": 0,
                "Ports": {},
                "SandboxKey": "/var/run/docker/netns/d2c3bcb24dad",
                "SecondaryIPAddresses": null,
                "SecondaryIPv6Addresses": null,
                "EndpointID": "06faf1bf029aa5d96017179c86613390b4ca444c4ec1785e5e509bbd0e176e50",
                "Gateway": "172.17.0.1",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "IPAddress": "172.17.0.2",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "MacAddress": "02:42:ac:11:00:02",
                "Networks": {
                    "bridge": {
                        "IPAMConfig": null,
                        "Links": null,
                        "Aliases": null,
                        "NetworkID": "6e4f2d692d68fa3fba8b2d60321107b37a12ecc09a56a8f9214e3a06801e41c1",
                        "EndpointID": "06faf1bf029aa5d96017179c86613390b4ca444c4ec1785e5e509bbd0e176e50",
                        "Gateway": "172.17.0.1",
                        "IPAddress": "172.17.0.2",
                        "IPPrefixLen": 16,
                        "IPv6Gateway": "",
                        "GlobalIPv6Address": "",
                        "GlobalIPv6PrefixLen": 0,
                        "MacAddress": "02:42:ac:11:00:02",
                        "DriverOpts": null
                    }
                }
            }
        }
    ]
    
  10. asottile commented on Nov 15, 2020

    @asottile
    Member

    there is one oddity for access(2) mentioned in the manpage:

           If the calling process is privileged (i.e., its real UID is zero),
           then an X_OK check is successful for a regular file if execute
           permission is enabled for any of the file owner, group, or other.
    

    though I don't think that applies here 🤔 -- I'm trying to boot a mac and see if I can reproduce this with plain docker

  11. asottile commented on Nov 15, 2020

    @asottile
    Member

    ok cool, this 100% looks like a docker bug:

    root@e41b7b11cbbc:/src# ls -al /tmp/x .pre-commit-config.yaml 
    -rw-r--r-- 1 root root 1216 May 25 00:49 .pre-commit-config.yaml
    -rw-r--r-- 1 root root    0 Nov 15 07:19 /tmp/x
    root@e41b7b11cbbc:/src# python3
    Python 3.9.0 (default, Oct 13 2020, 20:14:06) 
    [GCC 8.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os
    >>> os.access('/tmp/t', os.X_OK)
    False
    >>> os.access('.pre-commit-config.yaml', os.X_OK)
    True
  12. asottile commented on Nov 15, 2020

    @asottile
    Member

    here's the upstream bug -- I'd suggest following along there: docker/for-mac#5029

  13. ashwin153 commented on Aug 8, 2024

    @ashwin153

    @asottile This Docker bug is 4 years old now and the suggested workaround (use the legacy osxfs) slows down my devcontainer to a crawl, but this pre-commit hook has caught a lot of real issues for me in the past and I would rather keep it on. Is there a way I can disable the hook only when I'm developing on my mac?

  14. asottile commented on Aug 8, 2024

    @asottile
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions